[Orxonox-commit 3773] r8453 - in code/branches/tutoriallevel3: . data/gui/layouts data/gui/scripts data/levels data/overlays doc/api/groups src/libraries/core src/libraries/network/synchronisable src/libraries/util src/modules/notifications src/modules/objects/triggers src/modules/overlays/hud src/modules/questsystem src/orxonox src/orxonox/gametypes src/orxonox/infos src/orxonox/interfaces

dafrick at orxonox.net dafrick at orxonox.net
Thu May 12 00:31:23 CEST 2011


Author: dafrick
Date: 2011-05-12 00:31:23 +0200 (Thu, 12 May 2011)
New Revision: 8453

Added:
   code/branches/tutoriallevel3/data/levels/quests.oxw
   code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.cc
   code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.h
   code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.cc
Removed:
   code/branches/tutoriallevel3/src/modules/notifications/Notification.cc
   code/branches/tutoriallevel3/src/modules/notifications/Notification.h
   code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.cc
   code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.h
Modified:
   code/branches/tutoriallevel3/
   code/branches/tutoriallevel3/data/gui/layouts/QuestGUI.layout
   code/branches/tutoriallevel3/data/gui/scripts/NotificationLayer.lua
   code/branches/tutoriallevel3/data/gui/scripts/QuestGUI.lua
   code/branches/tutoriallevel3/data/gui/scripts/SingleplayerMenu.lua
   code/branches/tutoriallevel3/data/overlays/debug.oxo
   code/branches/tutoriallevel3/doc/api/groups/Triggers.dox
   code/branches/tutoriallevel3/src/libraries/core/GUIManager.cc
   code/branches/tutoriallevel3/src/libraries/core/GUIManager.h
   code/branches/tutoriallevel3/src/libraries/network/synchronisable/Synchronisable.cc
   code/branches/tutoriallevel3/src/libraries/util/SubString.h
   code/branches/tutoriallevel3/src/modules/notifications/CMakeLists.txt
   code/branches/tutoriallevel3/src/modules/notifications/NotificationDispatcher.cc
   code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.cc
   code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.h
   code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.cc
   code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.h
   code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.cc
   code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.h
   code/branches/tutoriallevel3/src/modules/objects/triggers/EventTrigger.h
   code/branches/tutoriallevel3/src/modules/objects/triggers/MultiTrigger.cc
   code/branches/tutoriallevel3/src/modules/objects/triggers/TriggerBase.h
   code/branches/tutoriallevel3/src/modules/overlays/hud/CMakeLists.txt
   code/branches/tutoriallevel3/src/modules/questsystem/QuestDescription.cc
   code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.cc
   code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.h
   code/branches/tutoriallevel3/src/orxonox/LevelManager.cc
   code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.cc
   code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.h
   code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.cc
   code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.h
   code/branches/tutoriallevel3/src/orxonox/interfaces/CMakeLists.txt
   code/branches/tutoriallevel3/src/orxonox/interfaces/InterfaceCompilation.cc
   code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.h
Log:
Merging tutoriallevel2 branch into tutoriallevel3 branch.



Property changes on: code/branches/tutoriallevel3
___________________________________________________________________
Modified: svn:mergeinfo
   - /code/branches/ai:6592-7033
/code/branches/buildsystem:1874-2276,2278-2400
/code/branches/buildsystem2:2506-2658
/code/branches/buildsystem3:2662-2708
/code/branches/ceguilua:1802-1808
/code/branches/chat:6527-6797
/code/branches/chat2:6836-6910
/code/branches/console:5941-6104
/code/branches/consolecommands2:6451-7178
/code/branches/consolecommands3:7178-7283
/code/branches/core3:1572-1739
/code/branches/core4:3221-3224,3227,3234-3238,3242,3244-3250,3252-3254,3256,3259-3261,3264-3265,3268-3275,3277-3278,3280,3284-3285,3287,3289-3294,3305,3309-3310
/code/branches/core5:5768-5928,6009
/code/branches/data_cleanup:7537-7686
/code/branches/doc:7290-7400
/code/branches/dynamicmatch:6584-7030
/code/branches/fps:6591-7072
/code/branches/gamestate:6430-6572,6621-6661
/code/branches/gamestates2:6594-6745
/code/branches/gametypes:2826-3031
/code/branches/gcc43:1580
/code/branches/gui:1635-1723,2795-2894
/code/branches/hudelements:6584-6941
/code/branches/ingamemenu:6000-6023
/code/branches/input:1629-1636
/code/branches/ipv6:7293-7458
/code/branches/kicklib:7940-8096,8098-8277
/code/branches/kicklib2:8282-8350
/code/branches/lastmanstanding:7479-7644
/code/branches/lastmanstanding3:7903-8175
/code/branches/libraries:5612-5692
/code/branches/libraries2:5703-5737
/code/branches/lod:6586-6911
/code/branches/lodfinal:2372-2411
/code/branches/mac_osx:7789-8128,8135
/code/branches/map:2801-3086,3089
/code/branches/masterserver:7502-7738
/code/branches/menu:5941-6146,6148,7536-7687
/code/branches/miniprojects:2754-2824
/code/branches/netp2:2835-2988
/code/branches/netp3:2988-3082
/code/branches/netp6:3214-3302
/code/branches/network:2356
/code/branches/network2:6434-6465
/code/branches/network3:7196-7344
/code/branches/network4:7497-7755
/code/branches/network5:7757-7781
/code/branches/network6:7823-8315
/code/branches/network64:2210-2355
/code/branches/notifications:7314-7401
/code/branches/objecthierarchy:1911-2085,2100,2110-2169
/code/branches/objecthierarchy2:2171-2479
/code/branches/ois_update:7506-7788
/code/branches/overlay:2117-2385
/code/branches/particles:2829-3085
/code/branches/particles2:6050-6106,6109
/code/branches/pch:3113-3194
/code/branches/physics:1912-2055,2107-2439
/code/branches/physics_merge:2436-2457
/code/branches/pickup2:5942-6405
/code/branches/pickup3:6418-6523
/code/branches/pickup4:6594-6710
/code/branches/pickups:1926-2086,2127,2827-2915
/code/branches/pickups2:2107-2497,2915-3071
/code/branches/png2:7262-7263
/code/branches/ppspickups1:6552-6708
/code/branches/ppspickups2:6527-6532,6554-6709
/code/branches/ppspickups3:6757-6997
/code/branches/ppspickups4:7003-7089
/code/branches/presentation:2369-2652,2654-2660,7736-7786
/code/branches/presentation2:6106-6416,7787-7800
/code/branches/presentation3:6913-7162
/code/branches/questsystem:1894-2088
/code/branches/questsystem2:2107-2259
/code/branches/questsystem5:2776-2905
/code/branches/releasetodo:7614-7647
/code/branches/resource:3327-3366
/code/branches/resource2:3372-5694
/code/branches/rocket:6523-6950
/code/branches/rocket2:6953-6970
/code/branches/script_trigger:1295-1953,1955
/code/branches/skybox2:6559-6989
/code/branches/sound:2829-3010
/code/branches/sound3:5941-6102
/code/branches/steering:5949-6091
/code/branches/tetris:8100-8107
/code/branches/usability:7915-8078
/code/branches/weapon:1925-2094
/code/branches/weapon2:2107-2488
/code/branches/weapons:2897-3051
/code/branches/weaponsystem:2742-2890
   + /code/branches/ai:6592-7033
/code/branches/buildsystem:1874-2276,2278-2400
/code/branches/buildsystem2:2506-2658
/code/branches/buildsystem3:2662-2708
/code/branches/ceguilua:1802-1808
/code/branches/chat:6527-6797
/code/branches/chat2:6836-6910
/code/branches/console:5941-6104
/code/branches/consolecommands2:6451-7178
/code/branches/consolecommands3:7178-7283
/code/branches/core3:1572-1739
/code/branches/core4:3221-3224,3227,3234-3238,3242,3244-3250,3252-3254,3256,3259-3261,3264-3265,3268-3275,3277-3278,3280,3284-3285,3287,3289-3294,3305,3309-3310
/code/branches/core5:5768-5928,6009
/code/branches/data_cleanup:7537-7686
/code/branches/doc:7290-7400
/code/branches/dynamicmatch:6584-7030
/code/branches/fps:6591-7072
/code/branches/gamestate:6430-6572,6621-6661
/code/branches/gamestates2:6594-6745
/code/branches/gametypes:2826-3031
/code/branches/gcc43:1580
/code/branches/gui:1635-1723,2795-2894
/code/branches/hudelements:6584-6941
/code/branches/ingamemenu:6000-6023
/code/branches/input:1629-1636
/code/branches/ipv6:7293-7458
/code/branches/kicklib:7940-8096,8098-8277
/code/branches/kicklib2:8282-8350
/code/branches/lastmanstanding:7479-7644
/code/branches/lastmanstanding3:7903-8175
/code/branches/libraries:5612-5692
/code/branches/libraries2:5703-5737
/code/branches/lod:6586-6911
/code/branches/lodfinal:2372-2411
/code/branches/mac_osx:7789-8128,8135
/code/branches/map:2801-3086,3089
/code/branches/masterserver:7502-7738
/code/branches/menu:5941-6146,6148,7536-7687
/code/branches/miniprojects:2754-2824
/code/branches/netp2:2835-2988
/code/branches/netp3:2988-3082
/code/branches/netp6:3214-3302
/code/branches/network:2356
/code/branches/network2:6434-6465
/code/branches/network3:7196-7344
/code/branches/network4:7497-7755
/code/branches/network5:7757-7781
/code/branches/network6:7823-8315
/code/branches/network64:2210-2355
/code/branches/notifications:7314-7401
/code/branches/objecthierarchy:1911-2085,2100,2110-2169
/code/branches/objecthierarchy2:2171-2479
/code/branches/ois_update:7506-7788
/code/branches/overlay:2117-2385
/code/branches/particles:2829-3085
/code/branches/particles2:6050-6106,6109
/code/branches/pch:3113-3194
/code/branches/physics:1912-2055,2107-2439
/code/branches/physics_merge:2436-2457
/code/branches/pickup2:5942-6405
/code/branches/pickup3:6418-6523
/code/branches/pickup4:6594-6710
/code/branches/pickups:1926-2086,2127,2827-2915
/code/branches/pickups2:2107-2497,2915-3071
/code/branches/png2:7262-7263
/code/branches/ppspickups1:6552-6708
/code/branches/ppspickups2:6527-6532,6554-6709
/code/branches/ppspickups3:6757-6997
/code/branches/ppspickups4:7003-7089
/code/branches/presentation:2369-2652,2654-2660,7736-7786
/code/branches/presentation2:6106-6416,7787-7800
/code/branches/presentation3:6913-7162
/code/branches/questsystem:1894-2088
/code/branches/questsystem2:2107-2259
/code/branches/questsystem5:2776-2905
/code/branches/releasetodo:7614-7647
/code/branches/resource:3327-3366
/code/branches/resource2:3372-5694
/code/branches/rocket:6523-6950
/code/branches/rocket2:6953-6970
/code/branches/script_trigger:1295-1953,1955
/code/branches/skybox2:6559-6989
/code/branches/sound:2829-3010
/code/branches/sound3:5941-6102
/code/branches/steering:5949-6091
/code/branches/tetris:8100-8107
/code/branches/tutoriallevel:7827-8370
/code/branches/tutoriallevel2:8370-8452
/code/branches/usability:7915-8078
/code/branches/weapon:1925-2094
/code/branches/weapon2:2107-2488
/code/branches/weapons:2897-3051
/code/branches/weaponsystem:2742-2890

Modified: code/branches/tutoriallevel3/data/gui/layouts/QuestGUI.layout
===================================================================
--- code/branches/tutoriallevel3/data/gui/layouts/QuestGUI.layout	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/data/gui/layouts/QuestGUI.layout	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,23 +1,78 @@
 <?xml version="1.0" ?>
 <GUILayout>
-    <Window Type="MenuWidgets/StaticImage" Name="orxonox/QuestGUI/Background">
-    <Property Name="UnifiedSize" Value="{{1.0,0},{1.0,0}}"/>
-    <Property Name="Image" Value="set:MainMenuBackground image:Background"/>
-    <Property Name="FrameEnabled" Value="set:true"/>
-    <Property Name="BackgroundEnabled" Value="set:false"/>
-    <Property Name="InheritsAlpha" Value="False" />
+    <Window Type="DefaultWindow" Name="orxonox/QuestGUI/Background">
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
 
-        <Window Type="MenuWidgets/Titlebar" Name="orxonox/QuestGUI/Title">
-            <Property Name="UnifiedPosition" Value="{{0.05,0},{0.05,0}}"/>
-            <Property Name="UnifiedSize" Value="{{0.9,0},{0.05,0}}"/>
-            <Property Name="Text" Value="Your Quests"/>
-        </Window>
+        <Window Type="DefaultWindow" Name="orxonox/QuestGUI/MainWindow">
+            <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.1,0},{0.9,0},{0.9,0}}" />
 
-        <Window Type="MenuWidgets/Listbox" Name="orxonox/QuestGUI/QuestsList">
-            <Property Name="UnifiedPosition" Value="{{0.07,0},{0.18,0}}" />
-            <Property Name="UnifiedSize" Value="{{0.86,0},{0.8,0}}" />
-            <Property Name="Alpha" Value="0.8" />
+            <Window Type="MenuWidgets/Titlebar" Name="orxonox/QuestGUI/Title">
+                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,30}}" />
+                <Property Name="Text" Value="Your Quests"/>
+            </Window>
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/MainWindow/LeftPanel">
+                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{0.5,0},{1,0}}" />
+
+                <Window Type="MenuWidgets/TabButton" Name="orxonox/QuestGUI/ActiveQuestsButton">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0.5,0},{0,30}}" />
+                    <Property Name="Text" Value="active quests"/>
+                    <Event Name="Clicked" Function="QuestGUI.showActiveQuestsButton_clicked"/>
+                </Window>
+                <Window Type="MenuWidgets/TabButton" Name="orxonox/QuestGUI/FinishedQuestsButton">
+                    <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0,0},{1,0},{0,30}}" />
+                    <Property Name="Text" Value="finished quests"/>
+                    <Event Name="Clicked" Function="QuestGUI.showFinishedQuestsButton_clicked"/>
+                </Window>
+
+                <Window Type="MenuWidgets/Listbox" Name="orxonox/QuestGUI/QuestsList">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{1,0},{1,0}}" />
+                    <Event Name="ItemSelectionChanged" Function="QuestGUI.changeQuest_clicked"/>
+                </Window>
+            </Window>
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/MainWindow/RightPanel">
+                <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0,30},{1,0},{1,0}}" />
+
+                <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Title">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,30}}" />
+                    <Property Name="Text" Value="Quest Title"/>
+                </Window>
+
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/QuestGUI/Quest/ScrollWrapper">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{1,-4},{1,-4}}" />
+
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Wrapper">
+                        <Property Name="UnifiedAreaRect" Value="{{0,5},{0,5},{1,-5},{0,0}}" />
+                        <Property Name="FrameEnabled" Value="false" />
+                        <Property Name="Alpha" Value="0" />
+
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Description">
+                            <Property Name="UnifiedAreaRect" Value="{{0,5},{0,0},{1,-5},{0,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Property Name="HorzFormatting" Value="WordWrapLeftAligned" />
+                            <Property Name="VertFormatting" Value="TopAligned" />
+                            <Property Name="FrameEnabled" Value="false" />
+                            <Property Name="Text" Value="Quest Description"/>
+                        </Window>
+
+                        <Window Type="MenuWidgets/Listbox" Name="orxonox/QuestGUI/Quest/SubquestsList">
+                            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Event Name="ItemSelectionChanged" Function="QuestGUI.changeToSubquest_clicked"/>
+                        </Window>
+
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Hints">
+                            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Property Name="VertFormatting" Value="TopAligned" />
+                            <Property Name="FrameEnabled" Value="false" />
+                            <Property Name="Text" Value="Hints:" />
+                        </Window>
+                    </Window>
+                </Window>
+            </Window>
         </Window>
-
     </Window>
 </GUILayout>

Modified: code/branches/tutoriallevel3/data/gui/scripts/NotificationLayer.lua
===================================================================
--- code/branches/tutoriallevel3/data/gui/scripts/NotificationLayer.lua	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/data/gui/scripts/NotificationLayer.lua	2011-05-11 22:31:23 UTC (rev 8453)
@@ -3,7 +3,6 @@
 local P = createMenuSheet("NotificationLayer", true, TriBool.True, TriBool.True)
 
 P.queueList = {}
-P.editMode = false
 
 P.sampleWindow = nil
 
@@ -16,20 +15,29 @@
 -- Creates a queue in the GUI.
 function P.createQueue(name, size)
     local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
-    local queue = winMgr:createWindow("MenuWidgets/Listbox", "orxonox/NotificationLayer/Root/Queue/" .. name)
-    queue:setProperty("BackgroundColor", "00FFFFFF") -- Set background to be fully transparent.
+    --local queue = winMgr:createWindow("MenuWidgets/Listbox", "orxonox/NotificationLayer/Root/Queue/" .. name)
+    --queue:setProperty("BackgroundColor", "00FFFFFF") -- Set background to be fully transparent.
+    local queue = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/Queue/" .. name)
+    queue:setProperty("Alpha", 0.0)
+    --queue:setProperty("FrameEnabled", "false")
     root:addChildWindow(queue)
 
-    queue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
-    queue:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, 0), CEGUI.UDim(0, P.queueHeightHelper(queue, size))))
-
     local queueTuple =
     {
-        ["window"]  = queue,
-        ["name"]    = name,
-        ["edit"]    = nil,
-        ["visible"] = false
+        ["window"]    = queue,
+        ["name"]      = name,
+        ["maxSize"]      = size,
+        ["visible"]   = false,
+        ["fontSize"]  = 12,
+        ["fontColor"] = "FFFFFFFF",
+        ["alignment"] = "LeftAligned",
+        ["items"]     = {},
+        ["first"]     = 1,
+        ["last"]      = 1
     }
+    
+    queue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+    queue:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, 0), CEGUI.UDim(0, P.queueHeightHelper(queueTuple, size))))
 
     P.queueList[name] = queueTuple -- name access
     P.setVisible(queueTuple, false) -- Set the queue to invisible as long as there are no notifications in it.
@@ -51,14 +59,28 @@
     if queue == nil then
         return
     end
-    item = CEGUI.createListboxTextItem(notification)
-    local listbox = CEGUI.toListbox(queue.window)
-    -- Add the item to the top of the listbox.
-    if listbox:getItemCount() == 0 then
-        listbox:addItem(item)
-    else
-        listbox:insertItem(item, listbox:getListboxItemFromIndex(0))
+
+    local item = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/Queue/" .. queueName .. "/" .. queue.last)
+    item:setText(notification)
+    P.setItemFontHelper(item, queue, true)
+    -- Add the item to the top of the queue.
+    local itemHeight = P.itemHeightHelper(queue)
+    if queue.last-queue.first > 0 then -- If the queue is not empty move all items down
+        for i=queue.first,queue.last-1 do
+            local item = queue.items[i]
+            item:setYPosition(CEGUI.UDim(0, itemHeight*(queue.last-i)))
+        end
     end
+    queue.window:addChildWindow(item)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(0, itemHeight)))
+    item:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+    item:setProperty("Alpha", 1.0)
+    item:setProperty("InheritsAlpha", "false")
+    item:setProperty("BackgroundEnabled", "false")
+    item:setProperty("FrameEnabled", "false")
+    item:setProperty("HorzFormatting", queue.alignment)
+    queue.items[queue.last] = item
+    queue.last = queue.last+1
 
     -- If the queue has been invisible, set it to visible.
     if queue.visible == false then
@@ -72,28 +94,53 @@
     if queue == nil then
         return
     end
-    local listbox = CEGUI.toListbox(queue.window)
-    -- Removes the item from the bottom of the listbox.
-    listbox:removeItem(listbox:getListboxItemFromIndex(listbox:getItemCount()-1))
+    local item = queue.items[queue.first]
+    -- Removes the item from the bottom of the queue.
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    queue.first = queue.first+1
 
     -- Sets the queue to invisible if there are no more notifications in it.
-    if listbox:getItemCount() == 0 then
+    if queue.last-queue.first == 0 then
         P.setVisible(queue, false)
     end
 end
 
--- Removes a notification at a given index from the queue.
+-- Removes a notification at a given index from the queue. Where the 0th item is the newest and the nth the (n+1)th newest.
 function P.removeNotification(queueName, index)
     local queue = P.queueList[queueName]
     if queue == nil then
         return
     end
-    local listbox = CEGUI.toListbox(queue.window)
+
+    index = queue.last-tonumber(index)-1
+    --if index == queue.first then -- If we want to remove the oldest notification, we can just use pop.
+    --    P.popNotification(queueName)
+    --    return
+    --end
+
     -- Removes the item.
-    listbox:removeItem(listbox:getListboxItemFromIndex(tonumber(index)))
+    local item = queue.items[index]
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    queue.items[index] = nil
 
+    -- Move the items below, up.
+    local itemHeight = P.itemHeightHelper(queue)
+    local moved = false
+    if index > queue.first then -- Move all older notifications up in the list.
+        for i=index-1,-1,queue.first do
+            cout(0, i)
+            item = queue.items[i]
+            item:setYposition(CEGUI.UDim(0, itemHeight*(queue.last-i-1)))
+            queue.items[i+1] = item
+        end
+    end
+    queue.items[queue.first] = nil
+    queue.first = queue.first+1
+
     -- Sets the queue to invisible if there are no more notifications in it.
-    if listbox:getItemCount() == 0 then
+    if queue.last-queue.first == 0 then
         P.setVisible(queue, false)
     end
 end
@@ -104,8 +151,14 @@
     if queue == nil then
         return
     end
-    local listbox = CEGUI.toListbox(queue.window)
-    CEGUI.toListbox(queue.window):resetList()
+    for i=queue.first,queue.last-1 do
+        local item = queue.items[i]
+        queue.window:removeChildWindow(item)
+        winMgr:destroyWindow(item)
+    end
+    queue.items = {}
+    queue.first = 1
+    queue.last = 1
 
     -- Sets the queue to invisible.
     P.setVisible(queue, false)
@@ -120,372 +173,119 @@
     queue.visible = visible
 end
 
--- Enter the edit mode of the notification layer.
-function P.enterEditMode()
-    P.editMode = true
+-- Change the position of the queue.
+-- The parameters are (in order) 'name of the queue', 'relative x-position', 'absolute x-position in pixel', 'relative y-position', 'absolute y-position in pixel'.
+function P.moveQueue(queueName, relativeXPos, absoluteXPos, relativeYpos, absoluteYPos)
+    local queueWindow = P.queueList[queueName].window
+    queueWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(relativeXPos, absoluteXPos), CEGUI.UDim(relativeYpos, absoluteYPos)))
+end
 
-    local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
-
-    --Add control frame window.
-    local window = winMgr:createWindow("MenuWidgets/FrameWindow", "orxonox/NotificationLayer/Root/EditMode/ControlWindow")
-    local frame = tolua.cast(window, "CEGUI::FrameWindow")
-    frame:setCloseButtonEnabled(false)
-    frame:setText("NotificationLayer Control Window")
-    frame:setSize(CEGUI.UVector2(CEGUI.UDim(0.7, 0), CEGUI.UDim(0.2, 0)))
-    root:addChildWindow(window)
-    local pane = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/ScrollingPane")
-    pane:setSize(CEGUI.UVector2(CEGUI.UDim(1,-20), CEGUI.UDim(1,-30)))
-    pane:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 10), CEGUI.UDim(0, 26)))
-    window:addChildWindow(pane)
-
-    vertOffset = 0
-    horzOffset = 0
-    -- Line to be able to create a new queue.
-    local newQueueTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueTitle")
-    newQueueTitle:setText("Create a new NotificationQueue:")
-    local size = getMinTextSize(newQueueTitle)
-    local textHeight = size[1]
-    newQueueTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight)))
-    newQueueTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    pane:addChildWindow(newQueueTitle)
-    horzOffset = horzOffset + size[2] + 5
-    local newQueueName = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueName")
-    newQueueName:setProperty("ReadOnly", "set:False")
-    newQueueName:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight)))
-    newQueueName:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    horzOffset = horzOffset + size[2] + 5
-    pane:addChildWindow(newQueueName)
-    local create = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/CreateNewQueue")
-    create:setText("create")
-    P.sampleWindow:setText("create")
-    size = getMinTextSize(P.sampleWindow)
-    create:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]+20), CEGUI.UDim(0, textHeight)))
-    create:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    orxonox.GUIManager:subscribeEventHelper(create, "Clicked", P.name .. ".createNewQueue_clicked")
-    pane:addChildWindow(create)
-    horzOffset = horzOffset + size[2]+20 + 5
-    vertOffset = vertOffset + textHeight + 5
-
-    horzOffset = 0
-    -- Button to leave the edit mode.
-    local leave = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/LeaveEditModeButton")
-    leave:setText("leave Edit Mode")
-    P.sampleWindow:setText("leave Edit Mode")
-    size = getMinTextSize(P.sampleWindow)
-    leave:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]+20), CEGUI.UDim(0, textHeight)))
-    leave:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    orxonox.GUIManager:subscribeEventHelper(leave, "Clicked", P.name .. ".leaveEditMode_clicked")
-    pane:addChildWindow(leave)
-    horzOffset = horzOffset + size[2]+20 + 5
-    vertOffset = vertOffset + textHeight + 5
-
-    --Replace all queues with FrameWindows
-    for k,v in pairs(P.queueList) do
-        if v ~= nil then
-            local queue = P.queueList[k]
-            -- Remove the window that displays the queue from the root window such that it is no longer displayed.
-            root:removeChildWindow(v.window)
-
-            -- Create the frame window, with options to edit the queue, that is displayed instead of the queue.
-            local window = P.createQueueEditFrame(v.name)
-            window:setArea(v.window:getArea()) -- Set the frame window size and position to the same as the queue.
-
-            v.edit = window
-        end
+-- Change the size of the queue.
+-- The parameters are (in order) 'name of the queue', 'relative width', 'absolute width in pixel', 'relative height', 'absolute heigth in pixel'.
+-- Additionally the last two parameters can be ommitted, which leads to the height being set such that all notifications can be displayed. using the size of the queue.
+function P.resizeQueue(queueName, relativeWidth, absoluteWidth, relativeHeight, absoluteHeigth)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
     end
+    if absoluteHeigth == nil then
+        absoluteHeigth = P.queueHeightHelper(queue, queue.maxSize)
+        relativeHeight = 0
+    end
+    queueWindow:setSize(CEGUI.UVector2(CEGUI.UDim(relativeWidth, absoluteWidth), CEGUI.UDim(relativeHeight, absoluteHeigth)))
 end
 
--- Helper function. Creates a frame for the input queue.
-function P.createQueueEditFrame(queueName)
-    local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
-
-    window = winMgr:createWindow("MenuWidgets/FrameWindow", "orxonox/NotificationLayer/Root/EditMode/" .. queueName)
-    local frame = tolua.cast(window, "CEGUI::FrameWindow")
-    frame:setCloseButtonEnabled(true)
-    orxonox.GUIManager:subscribeEventHelper(frame, "CloseClicked", P.name .. ".closeQueue_clicked")
-    frame:setText("NotificationQueue \"" .. queueName .. "\"")
-    root:addChildWindow(window)
-    local pane = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/ScrollingPane")
-    pane:setSize(CEGUI.UVector2(CEGUI.UDim(1,-20), CEGUI.UDim(1,-30)))
-    pane:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 10), CEGUI.UDim(0, 26)))
-    window:addChildWindow(pane)
-
-    local horzOffset = 0
-    local vertOffset = 0
-
-    -- The line that lets you edit the targets of the queue.
-    local targetsTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/TargetsTitle")
-    targetsTitle:setText("Targets:")
-    local size = getMinTextSize(targetsTitle)
-    local textHeight = size[1]
-    targetsTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight)))
-    targetsTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    pane:addChildWindow(targetsTitle)
-    horzOffset = horzOffset + size[2] + 5
-    local targets = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets")
-    targets:setProperty("ReadOnly", "set:False")
-    local targetsText = orxonox.NotificationManager:getInstance():getQueue(queueName):getTargets()
-    targets:setText(targetsText)
-    P.sampleWindow:setText(targetsText)
-    size = getMinTextSize(P.sampleWindow)
-    targets:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight)))
-    targets:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    horzOffset = horzOffset + size[2]*2+20 + 5
-    pane:addChildWindow(targets)
-    local save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets/Save")
-    save:setText("save")
-    P.sampleWindow:setText("save")
-    size = getMinTextSize(P.sampleWindow)
-    local saveTextWidth = size[2]+20
-    save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight)))
-    save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveTargets_clicked")
-    pane:addChildWindow(save)
-    horzOffset = horzOffset + saveTextWidth
-    vertOffset = vertOffset + textHeight + 5
-
-    horzOffset = 0
-    -- The line that lets you edit the size of the queue.
-    local sizeTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/SizeTitle")
-    sizeTitle:setText("Size:")
-    size = getMinTextSize(sizeTitle)
-    sizeTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight)))
-    sizeTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    pane:addChildWindow(sizeTitle)
-    horzOffset = horzOffset + size[2] + 5
-    local queueSize = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size")
-    queueSize:setProperty("ReadOnly", "set:False")
-    local maxSize = orxonox.NotificationManager:getInstance():getQueue(queueName):getMaxSize()
-    queueSize:setText(maxSize)
-    P.sampleWindow:setText(maxSize)
-    size = getMinTextSize(P.sampleWindow)
-    queueSize:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight)))
-    queueSize:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    horzOffset = horzOffset + size[2]*2+20 + 5
-    pane:addChildWindow(queueSize)
-    save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size/Save")
-    save:setText("save")
-    P.sampleWindow:setText("save")
-    size = getMinTextSize(P.sampleWindow)
-    local saveTextWidth = size[2]+20
-    save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight)))
-    save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveSize_clicked")
-    pane:addChildWindow(save)
-    horzOffset = horzOffset + saveTextWidth
-    vertOffset = vertOffset + textHeight + 5
-
-    horzOffset = 0
-    -- The line that lets you edit the display time of the queue.
-    local displayTimeTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTimeTitle")
-    displayTimeTitle:setText("Display time:")
-    size = getMinTextSize(displayTimeTitle)
-    displayTimeTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight)))
-    displayTimeTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    pane:addChildWindow(displayTimeTitle)
-    horzOffset = horzOffset + size[2] + 5
-    local displayTime = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime")
-    displayTime:setProperty("ReadOnly", "set:False")
-    local time = orxonox.NotificationManager:getInstance():getQueue(queueName):getDisplayTime()
-    displayTime:setText(time)
-    P.sampleWindow:setText(time)
-    size = getMinTextSize(P.sampleWindow)
-    displayTime:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight)))
-    displayTime:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    horzOffset = horzOffset + size[2]*2+20 + 5
-    pane:addChildWindow(displayTime)
-    save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime/Save")
-    save:setText("save")
-    P.sampleWindow:setText("save")
-    size = getMinTextSize(P.sampleWindow)
-    local saveTextWidth = size[2]+20
-    save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight)))
-    save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset)))
-    orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveDisplayTime_clicked")
-    pane:addChildWindow(save)
-    horzOffset = horzOffset + saveTextWidth
-    vertOffset = vertOffset + textHeight + 5
-
-    return window
-end
-
--- Leave the edit mode.
-function P.leaveEditMode()
-    P.editMode = false
-
-    local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
-    --Replace all queues with FrameWindows
-    for k,v in pairs(P.queueList) do
-        if v ~= nil then
-            -- Add the queue window to the root window to have it displayed again.
-            root:addChildWindow(v.window)
-            -- Set the size and position of the queue window to the size and position of the queue edit frame.
-            v.window:setArea(v.edit:getArea())
-            -- Destroy the edit frame.
-            winMgr:destroyWindow(v.edit)
-            v.edit = nil
-        end
+-- Change the horizontal alignment of the displayed notifications.
+-- The parameters are the name of the queue and the alignment parameter,
+function P.changeQueueAlignment(queueName, alignment)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
     end
 
-    --Remove control window
-    winMgr:destroyWindow(winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/ControlWindow"))
-end
-
--- Is called after the sheet has been hidden.
-function P.onQuit()
-    -- If we leave the edit mode we show the sheet again.
-    if P.editMode then
-        P.leaveEditMode()
-        showMenuSheet(P.name, false, true)
+    queue.alignment = alignment
+    local item = nil
+    for i=queue.first,queue.last-1 do
+        item = queue.items[i]
+        item:setProperty("HorzFormatting", queue.alignment)
     end
 end
 
--- If the button to save the targets of a queue has been clicked.
-function P. saveTargets_clicked(e)
-    local we = CEGUI.toWindowEventArgs(e)
-    local name = we.window:getName()
-
-    local match = string.gmatch(name, "EditMode/.*/Targets/Save")
-    local nameStr = match()
-    local queueName = string.sub(nameStr, 10, string.len(nameStr)-13)
-
-    local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets")
-    local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets/Save")
-    local width = window:getWidth():asAbsolute(1)
-
-    local queue = orxonox.NotificationManager:getInstance():getQueue(queueName)
-    -- Set the new targets.
-    queue:setTargets(window:getText())
-    local targets = queue:getTargets()
-
-    window:setText(targets)
-    P.sampleWindow:setText(targets)
-    local size = getMinTextSize(P.sampleWindow)
-    -- Adjust the width of the targets field.
-    window:setWidth(CEGUI.UDim(0, size[2]*2+20))
-    -- Adjust the position of the save button after the targets field.
-    save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1)))
-end
-
--- If the button to save the size if a queue has been clicked.
-function P. saveSize_clicked(e)
-    local we = CEGUI.toWindowEventArgs(e)
-    local name = we.window:getName()
-
-    local match = string.gmatch(name, "EditMode/.*/Size/Save")
-    local nameStr = match()
-    local queueName = string.sub(nameStr, 10, string.len(nameStr)-10)
-
-    local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size")
-    local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size/Save")
-    local width = window:getWidth():asAbsolute(1)
-
-    local queue = orxonox.NotificationManager:getInstance():getQueue(queueName)
-    -- Set the new size.
-    queue:setMaxSize(tonumber(window:getText()))
-    local maxSize = queue:getMaxSize()
-
-    window:setText(maxSize)
-    P.sampleWindow:setText(maxSize)
-    local size = getMinTextSize(P.sampleWindow)
-    -- Adjust the width of the size field.
-    window:setWidth(CEGUI.UDim(0, size[2]*2+20))
-    -- Adjust the position of the save button after the size field.
-    save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1)))
-end
-
--- If the button to save the display time if a queue has been clicked.
-function P. saveDisplayTime_clicked(e)
-    local we = CEGUI.toWindowEventArgs(e)
-    local name = we.window:getName()
-
-    local match = string.gmatch(name, "EditMode/.*/DisplayTime/Save")
-    local nameStr = match()
-    local queueName = string.sub(nameStr, 10, string.len(nameStr)-17)
-
-    local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime")
-    local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime/Save")
-    local width = window:getWidth():asAbsolute(1)
-
-    local queue = orxonox.NotificationManager:getInstance():getQueue(queueName)
-    -- Set the new display time.
-    queue:setDisplayTime(tonumber(window:getText()))
-    local time = queue:getDisplayTime()
-
-    window:setText(time)
-    P.sampleWindow:setText(time)
-    local size = getMinTextSize(P.sampleWindow)
-    -- Adjust the width of the display time field.
-    window:setWidth(CEGUI.UDim(0, size[2]*2+20))
-    -- Adjust the position of the save button after the display time field.
-    save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1)))
-end
-
--- if the button to create a new queue has been clicked.
-function P.createNewQueue_clicked(e)
-    local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueName")
-    local name = window:getText()
-
-    local queue = P.queueList[name]
-    -- Test if a queue with that name already exists.
-    if queue ~= nil then
-        window:setText("Queue with that name already exists.")
+-- Change the font size  of all notifications in a queue.
+-- The parameters are (in order) 'name of the queue', 'font size'.
+function P.changeQueueFontSize(queueName, size)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
         return
     end
 
-    -- Creates the new queue.
-    orxonox.NotificationManager:getInstance():createQueue(name)
+    queue.fontSize = size
+    for i=queue.first,queue.last-1 do
+        P.setItemFontHelper(queue.items[i], queue, false)
+    end
+end
 
-    queue = P.queueList[name]
-    if queue == nil then
+-- Change the font color of all notifications in a queue.
+-- The parameters are (in order) 'name of the queue', 'ARGB of the font color in hex notation'.
+function P.changeQueueFontColor(queueName, color)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
         return
     end
 
-    -- Create the frame that represents the queue in edit mode, since that's what we're in.
-    local frame = P.createQueueEditFrame(name)
-    local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
-    -- Remove the queue window from the root window, since we're in edit mode.
-    root:removeChildWindow(queue.window)
-    -- Set the frame window size and position to that of the queue window.
-    frame:setArea(queue.window:getArea())
-    queue.edit = frame
-
-    -- Reset the text to create a new queue.
-    window:setText("")
+    queue.fontColor = color
+    for i=queue.first,queue.last-1 do
+        P.setItemFontHelper(queue.items[i], queue, true)
+    end
 end
 
--- If the button to leave the edit mode has been clicked.
-function P.leaveEditMode_clicked(e)
-    hideMenuSheet(P.name)
+-- Helper function to set the font size and color of a item of a queue.
+-- The parameters are (in order) 'the ListboxItem', 'the queue table', 'whether color should be changed as well'
+function P.setItemFontHelper(item, queue, changeColor)
+    --local item = tolua.cast(item, "CEGUI::ListboxTextItem")
+    local fontMgr = CEGUI.FontManager:getSingleton()
+    if fontMgr:isFontPresent("BlueHighway-" .. queue.fontSize) then
+        item:setFont("BlueHighway-" .. queue.fontSize)
+    else
+        orxonox.GUIManager:addFontHelper("BlueHighway-" .. queue.fontSize, queue.fontSize, "bluehigh.ttf")
+        item:setFont("BlueHighway-" .. queue.fontSize)
+    end
+    if changeColor then
+        item:setProperty("TextColours", "tl:" .. queue.fontColor .. " tr:" .. queue.fontColor .. " bl:" .. queue.fontColor .. " br:" .. queue.fontColor .. "")
+    end
 end
 
--- If the button to close the queue has been clicked.
-function P.closeQueue_clicked(e)
-    local we = CEGUI.toWindowEventArgs(e)
-    local name = we.window:getName()
-
-    local match = string.gmatch(name, "EditMode/.*")
-    local nameStr = match()
-    local queueName = string.sub(nameStr, 10, string.len(nameStr))
-
-    -- Destroy the frame window,
-    winMgr:destroyWindow(P.queueList[queueName].edit)
-    P.queueList[queueName].edit = nil
-    -- Destroy the queue.
-    orxonox.NotificationManager:getInstance():getQueue(queueName):destroy()
-end
-
 -- Helper function. Returns height a queue needs to have to display 'size' items.
 function P.queueHeightHelper(queue, size)
-    local listbox = CEGUI.toListbox(queue)
-    local item = CEGUI.createListboxTextItem("Text")
-    listbox:addItem(item)
-    local singleItemHeight = listbox:getTotalItemsHeight()
-    local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(queue:getLookNFeel())
-    local formattedArea = lookAndFeel:getNamedArea("ItemRenderingArea"):getArea():getPixelRect(queue)
-    local frameHeight = queue:getUnclippedOuterRect():getHeight() - formattedArea:getHeight()
-    listbox:removeItem(item)
-    return frameHeight + singleItemHeight*size
+    --local listbox = CEGUI.toListbox(queue.window)
+    --local item = CEGUI.createListboxTextItem("Text")
+    --P.setItemFontHelper(item, queue, false)
+    --listbox:addItem(item)
+    --local singleItemHeight = listbox:getTotalItemsHeight()
+    local singleItemHeight = P.itemHeightHelper(queue)
+    --local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(queue.window:getLookNFeel())
+    --local formattedArea = lookAndFeel:getNamedArea("ItemRenderingArea"):getArea():getPixelRect(queue.window)
+    --local frameHeight = queue.window:getUnclippedOuterRect():getHeight() - formattedArea:getHeight()
+    --listbox:removeItem(item)
+    --return frameHeight + singleItemHeight*size
+    return singleItemHeight*size + 1
 end
 
+function P.itemHeightHelper(queue)
+    local item = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/Test/")
+    item:setText("text")
+    P.setItemFontHelper(item, queue, true)
+    queue.window:addChildWindow(item)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(1, 0)))
+    item:setProperty("FrameEnabled", "false")
+    local height = getStaticTextWindowHeight(item)
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    return height
+end
+
 return P

Modified: code/branches/tutoriallevel3/data/gui/scripts/QuestGUI.lua
===================================================================
--- code/branches/tutoriallevel3/data/gui/scripts/QuestGUI.lua	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/data/gui/scripts/QuestGUI.lua	2011-05-11 22:31:23 UTC (rev 8453)
@@ -2,33 +2,323 @@
 
 local P = createMenuSheet("QuestGUI")
 
-P.rootWindow = nil
-P.detailsWindows = {}
+P.questManager = nil -- The QuestManager.
+P.showActive = true -- Whether the active or finished quest list is displayed.
+P.currentQuest = nil -- The quest that is currently displayed.
+P.player = nil -- The player the quests are displayed for.
 P.quests = {}
-P.hints = {}
-P.player = nil
+P.subquests = {}
 
 -- design parameters
-P.indentWidth = 20
 P.scrollbarWidth = 13
-P.buttonHeight = 30
+P.frameHeigth = 18
+P.borderSize = 5
 P.titleHeight = 26
-P.borderWidth = 5
 
-function P.onShow()
+--TODO:
+-- Highlight whether we are currently looking at active or finished quests
+-- Distinguish completed from failed quests
 
-    local questsList = winMgr:getWindow("orxonox/QuestGUI/QuestsList")
+function P.onLoad()
+    P.questManager = orxonox.QuestManager:getInstance() -- Store the pointer to the QuestManager as an internal variable to allow for faster access,
+end
 
+function P.onShow()
+    -- Get the player.
     P.player = orxonox.GUIManager:getInstance():getPlayer(P.name)
-    P.rootWindow = P.createQuestGUI()
 
-    questsList:addChildWindow(P.rootWindow)
+    -- Load the list of quests to be displayed.
+    P.loadQuestsList(P.currentQuest)
 end
 
-function P.onHide()
-    P.cleanup()
+-- Loads the list of quests, depending on P.showActive, either the active (P.showActive == true) or the finished, i.e. inactive quests are loaded.
+-- selectQuest is a pointer to a quest that should be selected, if it is nil the first quest is selected.
+function P.loadQuestsList(selectQuest)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    P.clearQuestList()
+
+    local selectQuestId = nil
+    if selectQuest ~= nil then
+        selectQuestId = P.questManager:getId(selectQuest)
+    end
+
+    -- Iterate through all root-quests.
+    local numRootQuests = P.questManager:getNumRootQuests(P.player)
+    if numRootQuests > 0 then
+        local i = 0
+        while i <= numRootQuests-1 do
+            local quest = P.questManager:getRootQuest(P.player, i)
+            -- Insert the current quest into the list.
+            local item = P.insertQuest(list, quest)
+            -- If the quest was inserted in the list and is has the same id as the selectQuest (thus it is the same quest) it is selected.
+            if selectQuestId ~= nil and item ~= nil and selectQuestId == P.questManager:getId(quest) then
+                list:setItemSelectState(item, true)
+            end
+            -- Insert all subquests of this rootquest.
+            P.insertSubQuests(list, quest, selectQuestId)
+            i = i+1
+        end
+        -- If there were quests added to the list but there was no selectQuest specified (i.e. selectQuest was nil), the first item is selected.
+        if list:getItemCount() > 0 then
+            if selectQuestId == nil then
+                list:setItemSelectState(list:getListboxItemFromIndex(0), true)  -- Select first quest.
+            end
+        -- If there werent any quests added the standard "no quests" message is loaded.
+        else
+            P.loadQuest()
+        end
+    end
 end
 
+-- Helper function, recursively inserts all the (active or inactive, depending on P.showActive) subquests of the input quest.
+-- list is the list into which the subquests should be insterted.
+-- quest is the quest, whose subquests should be inserted.
+-- selectQuestId is the id of the quest that should be selected.
+function P.insertSubQuests(list, quest, selectQuestId)
+    -- Iterate through all sub-quests.
+    local numQuests = P.questManager:getNumSubQuests(quest, P.player)
+    if numQuests > 0 then
+        local i = 0
+        while i <= numQuests-1 do
+            local subquest = P.questManager:getSubQuest(quest, P.player, i)
+            -- Insert the current quest into the list.
+            local item = P.insertQuest(list, subquest)
+            -- If the quest was inserted in the list and is has the same id as the selectQuest (thus it is the same quest) it is selected.
+            if selectQuestId ~= nil and item ~= nil and selectQuestId == P.questManager:getId(subquest) then
+                list:setItemSelectState(item, true)
+            end
+            i = i+1
+        end
+    end
+end
+
+-- Helper function, inserts a quest into the list (depending whether active or inactive quests are being shown). Returns nil if the quest was not inserted.
+-- list is the list into which the quets should be inserted.
+-- quest is the quest to be inserted.
+function P.insertQuest(list, quest)
+    if P.showActive == quest:isActive(P.player) then
+        local item = CEGUI.createListboxTextItem(P.questManager:getDescription(quest):getTitle())
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        list:addItem(item)
+        table.insert(P.quests, quest)
+        return item
+    end
+    return nil
+end
+
+-- Loads the input quest.
+-- quest the quest to be loaded.
+function P.loadQuest(quest)
+
+    P.clearQuest() -- Clear the old quest.
+    if quest == nil then -- If quets is nil there is nothing to display.
+        return
+    else
+        local offset = 0
+
+        -- Load title and description
+        local description = P.questManager:getDescription(quest)
+        local titleWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Title")
+        titleWindow:setText(description:getTitle())
+        local descriptionWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Description")
+        descriptionWindow:setText(description:getDescription())
+        descriptionWindow:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(1, 0)))
+        descriptionWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, P.borderSize)))
+        local height = getStaticTextWindowHeight(descriptionWindow)
+        descriptionWindow:setHeight(CEGUI.UDim(0, height))
+        offset = offset + height
+
+        -- Load subquests
+        local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+        local numQuests = P.questManager:getNumSubQuests(quest, P.player)
+        local i = 0
+        while i <= numQuests-1 do
+            local quest = P.questManager:getSubQuest(quest, P.player, i)
+            local item = CEGUI.createListboxTextItem(P.questManager:getDescription(quest):getTitle())
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            list:addItem(item)
+            table.insert(P.subquests, quest)
+            i = i+1
+        end
+        height = list:getTotalItemsHeight()
+        if height > 0 then
+            height = height+P.frameHeigth
+        end
+        list:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(0, height)))
+        list:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+        offset = offset + height + P.borderSize
+
+        -- Load hints
+        local hintsWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Hints")
+        hintsWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+        hintsWindow:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(0, 0)))
+        height = P.titleHeight
+        local numHints = P.questManager:getNumHints(quest, P.player)
+        local i = 0
+        while i <= numHints-1 do
+            local hint = P.questManager:getHints(quest, P.player, i)
+            height = height + P.insertHint(hintsWindow, hint, i, height)
+            i = i+1
+        end
+        if numHints == 0 then
+            height = 0
+        end
+        hintsWindow:setHeight(CEGUI.UDim(0, height))
+        offset = offset + height
+
+        -- Set the size of the wrapper
+        local window = winMgr:getWindow("orxonox/QuestGUI/Quest/Wrapper")
+        window:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize-P.scrollbarWidth), CEGUI.UDim(0,offset+P.borderSize)))
+    end
+
+    P.currentQuest = quest
+end
+
+-- Clear the currently displayed quest.
+function P.clearQuest()
+    -- clear title
+    local titleWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Title")
+    titleWindow:setText("no Quests")
+
+    -- clear description
+    local descriptionWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Description")
+    descriptionWindow:setText("There is currently no quest that can be displayed.")
+
+    -- clear list fo subquests
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+    list:resetList()
+    list:setHeight(CEGUI.UDim(0, 0))
+    P.subquests = {}
+
+    -- clear hints
+    local hints = winMgr:getWindow("orxonox/QuestGUI/Quest/Hints")
+    local numChildren = hints:getChildCount()-2 -- TODO: HACK
+    local i = 0
+    while i < numChildren do
+        local hint = hints:getChild("orxonox/QuestGUI/Quest/Hints/" .. i)
+        if hint ~= nil then
+            hints:removeChildWindow(hint)
+            winMgr:destroyWindow(hint)
+        end
+        i = i+1
+    end
+    hints:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.scrollbarWidth-P.borderSize), CEGUI.UDim(0, 0)))
+
+    P.currentQuest = nil
+end
+
+-- Clear the quests list
+function P.clearQuestList()
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    list:resetList()
+    P.quests = {}
+end
+
+-- Select an input quest in the input list.
+-- list is the list in which the input quest is to be selected.
+-- quest is the quest to be selected.
+function P.selectQuest(list, quest)
+    if quest == nil then -- If the input quest is nil, there is nothing to be selected, an error is output and the first quest is selected instead.
+        cout(1, "Error in QuestGUI: selectQuest(), input quest is nil. Selecting first.")
+        list:setItemSelectState(list:getListboxItemFromIndex(0), true) -- Select first
+        return
+    end
+
+    local questId = P.questManager:getId(quest)
+    local found = false
+    local index = 0
+    -- Iterate over all quests currently in the list.
+    for k,v in pairs(P.quests) do
+        -- If the id's are the same we have found the quest.
+        if P.questManager:getId(v) == questId then
+            found = true
+            index = k-1
+        end
+    end
+
+    if found then -- If the quest was found it is selected.
+        list:setItemSelectState(list:getListboxItemFromIndex(index), true)
+    else -- If the quest isn't found an error is output and the first quest is selected instead.
+        cout(1, "Error in QuestGUI: selectQuest(), input quest is not in list. Selecting first.")
+        list:setItemSelectState(list:getListboxItemFromIndex(0), true) -- Select first
+    end
+end
+
+-- Helper function, insert the input hint into the input hintsWindow. Returns the height of the newly inserted hint.
+-- hintsWindow is the window in which the hint is to be inserted.
+-- hint is the hint to be inserted.
+-- index is the index of the hint.
+-- offset is the current offset in the hintsWindow.
+function P.insertHint(hintsWindow, hint, index, offset)
+    -- Create the window for the hint.
+    local window = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/QuestGUI/Quest/Hints/" .. index)
+    window:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    window:setProperty("VertFormatting", "TopAligned")
+    window:setProperty("FrameEnabled", "false")
+    window:setID(index)
+    hintsWindow:addChildWindow(window)
+    local description = P.questManager:getDescription(hint)
+    window:setText(description:getDescription())
+    window:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(1, 0)))
+    local height = getStaticTextWindowHeight(window)
+    window:setHeight(CEGUI.UDim(0, height))
+    window:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+    return height
+end
+
+-- Show the currently active quests in the quests list.
+function P.showActiveQuestsButton_clicked(e)
+    if P.showActive == false then
+        P.showActive = true
+        P.loadQuestsList()
+    end
+end
+
+-- Show the finished (i.e. inactive) quests in the quests list.
+function P.showFinishedQuestsButton_clicked(e)
+    if P.showActive == true then
+        P.showActive = false
+        P.loadQuestsList()
+    end
+end
+
+-- Change to a new quest.
+function P.changeQuest_clicked(e)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    local choice = list:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = list:getItemIndex(choice)
+        local quest = P.quests[index+1]
+        if quest ~= nil then
+            P.loadQuest(quest)
+        end
+    end
+end
+
+-- Change to a new subquest.
+function P.changeToSubquest_clicked(e)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+    local questsList = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    local choice = list:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = list:getItemIndex(choice)
+        local quest = P.subquests[index+1]
+        if quest ~= nil then
+            -- If the P.showActive must be changed to display the quest the quests list also has to be regenerated.
+            if quest:isActive(P.player) == P.showActive then
+                P.selectQuest(questsList, quest)
+            else
+                P.showActive = quest:isActive(P.player)
+                P.loadQuestsList(quest)
+            end
+        else
+            cout(1, "Error in QuestGUI: changeToSubquest(), quest was nil. Ignoring...")
+        end
+    end
+end
+
+-- old:
+--[[
 function P.createQuestGUI()
     local questManager = orxonox.QuestManager:getInstance()
 
@@ -282,7 +572,7 @@
 
     winMgr:destroyWindow(P.detailsWindows[detailsNr])
     P.detailsWindows[detailsNr] = nil
-end
+end --]]
 
 return P
 

Modified: code/branches/tutoriallevel3/data/gui/scripts/SingleplayerMenu.lua
===================================================================
--- code/branches/tutoriallevel3/data/gui/scripts/SingleplayerMenu.lua	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/data/gui/scripts/SingleplayerMenu.lua	2011-05-11 22:31:23 UTC (rev 8453)
@@ -53,6 +53,7 @@
         end
         index = index + 1
     end
+
     for k,v in pairs(P.levelList) do
         local item = CEGUI.createListboxTextItem(v:getName())
         item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")

Copied: code/branches/tutoriallevel3/data/levels/quests.oxw (from rev 8452, code/branches/tutoriallevel2/data/levels/quests.oxw)
===================================================================
--- code/branches/tutoriallevel3/data/levels/quests.oxw	                        (rev 0)
+++ code/branches/tutoriallevel3/data/levels/quests.oxw	2011-05-11 22:31:23 UTC (rev 8453)
@@ -0,0 +1,231 @@
+<LevelInfo
+ name = "Quests showcase"
+ description = "Level to test and showcase quests."
+ tags = "test, showcase"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ name         = "Questsystem"
+ description  = "Just a few tests"
+>
+    <templates>
+        <Template link=lodtemplate_default />
+    </templates>
+
+    <Scene
+        ambientlight = "0.5, 0.5, 0.5"
+        skybox       = "Orxonox/Starbox"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+        <GlobalQuest id="quest0">
+            <QuestDescription title="Quest 0" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+            Ut consequat leo ut quam congue semper et eget nibh. Nunc sit amet velit eu lorem pretium adipiscing eu ut ante. Nulla facilisi. Pellentesque interdum, neque nec consectetur vulputate, mauris risus feugiat nunc, ac sollicitudin neque quam ut tellus. Morbi elit velit, tincidunt et hendrerit eget, rutrum at erat. Duis eros nulla, faucibus vitae blandit vitae, pharetra sollicitudin justo." failMessage="Fail message 0" completeMessage="Complete message 0" />
+        </GlobalQuest>
+        <GlobalQuest id="quest1">
+            <QuestDescription title="Quest 1" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." failMessage="Fail message 1" completeMessage="Complete message 1" />
+            <hints>
+                <QuestHint id="quest1hint1">
+                    <QuestDescription title="The super Hint." description="Be proud of yourself." />
+                </QuestHint>
+                <QuestHint id="quest1hint2">
+                    <QuestDescription title="The super Hint2." description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." />
+                </QuestHint>
+                <QuestHint id="quest1hint3">
+                    <QuestDescription title="The super Hint3." description="Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus." />
+                </QuestHint>
+            </hints>
+            <subquests>
+                <GlobalQuest id="quest1.1">
+                    <QuestDescription title="Quest 1: Subquest 1" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.2">
+                    <QuestDescription title="Quest 1: Subquest 2" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.3">
+                    <QuestDescription title="Quest 1: Subquest 3" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.4">
+                    <QuestDescription title="Quest 1: Subquest 4" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.5">
+                    <QuestDescription title="Quest 1: Subquest 5" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+            </subquests>
+        </GlobalQuest>
+        <GlobalQuest id="quest2">
+            <QuestDescription title="Quest 2" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac." failMessage="Fail message 2" completeMessage="Complete message 2" />
+        </GlobalQuest>
+        <GlobalQuest id="quest3">
+            <QuestDescription title="Quest 3" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest4">
+            <QuestDescription title="Quest 4" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+            Ut consequat leo ut quam congue semper et eget nibh. Nunc sit amet velit eu lorem pretium adipiscing eu ut ante. Nulla facilisi. Pellentesque interdum, neque nec consectetur vulputate, mauris risus feugiat nunc, ac sollicitudin neque quam ut tellus. Morbi elit velit, tincidunt et hendrerit eget, rutrum at erat. Duis eros nulla, faucibus vitae blandit vitae, pharetra sollicitudin justo. Donec luctus est a tortor auctor feugiat." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest5">
+            <QuestDescription title="Quest 5" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest6">
+            <QuestDescription title="Quest 6" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. " failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+
+        <EventMultiTrigger name=spawntrigger>
+            <events>
+                <trigger>
+                    <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+                </trigger>
+            </events>
+        </EventMultiTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="quest0" />
+                <AddQuest questId="quest1" />
+                <AddQuest questId="quest1.1" />
+                <AddQuest questId="quest1.2" />
+                <AddQuest questId="quest1.3" />
+                <AddQuest questId="quest1.4" />
+                <AddQuest questId="quest1.5" />
+                <AddQuest questId="quest2" />
+                <AddQuest questId="quest3" />
+                <AddQuest questId="quest4" />
+                <AddQuest questId="quest5" />
+                <AddQuest questId="quest6" />
+                <AddQuestHint hintId ="quest1hint1" />
+                <AddQuestHint hintId ="quest1hint2" />
+                <AddQuestHint hintId ="quest1hint3" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="-100,0,0" times=1>
+            <effects>
+                <FailQuest questId="quest1.1" />
+                <FailQuest questId="quest1.2" />
+                <FailQuest questId="quest1.3" />
+                <FailQuest questId="quest1.4" />
+                <FailQuest questId="quest1.5" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=dtrigger1 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,0,0" material="Examples/Flare" />
+                <DistanceTrigger name=dtrigger1 position="0,0,0" distance=10 target="Pawn" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="100,0,0" times=-1>
+            <effects>
+                <CompleteQuest questId="quest0" />
+                <CompleteQuest questId="quest1" />
+                <CompleteQuest questId="quest1.1" />
+                <CompleteQuest questId="quest1.2" />
+                <CompleteQuest questId="quest1.3" />
+                <CompleteQuest questId="quest1.4" />
+                <CompleteQuest questId="quest1.5" />
+                <CompleteQuest questId="quest2" />
+                <CompleteQuest questId="quest3" />
+                <CompleteQuest questId="quest4" />
+                <CompleteQuest questId="quest5" />
+                <CompleteQuest questId="quest6" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=dtrigger2 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,1.0,0" material="Examples/Flare" />
+                <DistanceTrigger name=dtrigger2 position="0,0,0" distance=10 target="Pawn" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <!--QuestEffectBeacon position="0,0,100" times=-1>
+            <effects>
+                <AddQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt1 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt1 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="-100,0,0" times=-1>
+            <effects>
+                <FailQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt2 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt2 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="100,0,0" times=-1>
+            <effects>
+                <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt3 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,1.0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt3 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="0,100,0" times=-1>
+            <effects>
+                <AddQuestHint hintId="022a859d-08dd-4eac-a085-c28c29c06d48" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt4 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt4 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+            <events>
+                <activity>
+                    <QuestListener questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" mode="complete" />
+                </activity>
+            </events>
+        </ParticleEmitter-->
+
+    </Scene>
+</Level>
+

Modified: code/branches/tutoriallevel3/data/overlays/debug.oxo
===================================================================
--- code/branches/tutoriallevel3/data/overlays/debug.oxo	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/data/overlays/debug.oxo	2011-05-11 22:31:23 UTC (rev 8453)
@@ -83,13 +83,5 @@
      align    = "center"
     />
 
-    <GametypeStatus
-     name     = "state"
-     position = "0.5, 0.85"
-     font     = "VeraMono"
-     textsize = 0.05
-     colour   = "1.0, 1.0, 0.0, 0.8"
-     align    = "center"
-    />
   </OverlayGroup>
 </Template>

Modified: code/branches/tutoriallevel3/doc/api/groups/Triggers.dox
===================================================================
--- code/branches/tutoriallevel3/doc/api/groups/Triggers.dox	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/doc/api/groups/Triggers.dox	2011-05-11 22:31:23 UTC (rev 8453)
@@ -54,7 +54,7 @@
     - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceTrigger "DistanceTrigger" still triggers, i.e. its range. Default is <code>100</code>.
     - @b target Which specifies the class of objects that can trigger the @ref orxonox::DistanceTrigger "DistanceTrigger". Default is <code>"Pawn"</code>.
     - @b beaconMode Which specifies, whether the @ref orxonox::DistanceTrigger "DistanceTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
-    - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceTrigger "DistanceTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+    - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceTrigger "DistanceTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
 
     A simple @ref orxonox::DistanceTrigger "DistanceTrigger" could look like this:
     @code

Modified: code/branches/tutoriallevel3/src/libraries/core/GUIManager.cc
===================================================================
--- code/branches/tutoriallevel3/src/libraries/core/GUIManager.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/libraries/core/GUIManager.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -36,12 +36,14 @@
 
 #include <CEGUIDefaultLogger.h>
 #include <CEGUIExceptions.h>
+#include <CEGUIFontManager.h>
 #include <CEGUIInputEvent.h>
 #include <CEGUIMouseCursor.h>
 #include <CEGUIResourceProvider.h>
 #include <CEGUISystem.h>
 #include <CEGUIWindow.h>
 #include <CEGUIWindowManager.h>
+#include <CEGUIXMLAttributes.h>
 #include <elements/CEGUIListbox.h>
 #include <elements/CEGUIListboxItem.h>
 
@@ -662,4 +664,39 @@
             this->mouseLeft();
     }
 
+    /**
+    @brief
+        Adds a new freetype font to the CEGUI system.
+    @param name
+        The name of the new font.
+    @param size
+        The font size of the new font in pixels.
+        @param fontName
+        The filename of the font.
+    */
+    /*static*/ void GUIManager::addFontHelper(const std::string& name, int size, const std::string& fontName)
+    {
+        if(CEGUI::FontManager::getSingleton().isFontPresent(name)) // If a font with that name already exists.
+            return;
+
+        CEGUI::Font* font = NULL;
+        CEGUI::XMLAttributes xmlAttributes;
+
+        // Attributes specified within CEGUIFont
+        xmlAttributes.add("Name", name);
+        xmlAttributes.add("Filename", fontName);
+        xmlAttributes.add("ResourceGroup", "");
+        xmlAttributes.add("AutoScaled", "true");
+        xmlAttributes.add("NativeHorzRes", "800");
+        xmlAttributes.add("NativeVertRes", "600");
+
+        // Attributes specified within CEGUIXMLAttributes
+        xmlAttributes.add("Size", multi_cast<std::string>(size));
+        xmlAttributes.add("AntiAlias", "true");
+
+        font = CEGUI::FontManager::getSingleton().createFont("FreeType", xmlAttributes);
+        if(font != NULL)
+            font->load();
+    }
+
 }

Modified: code/branches/tutoriallevel3/src/libraries/core/GUIManager.h
===================================================================
--- code/branches/tutoriallevel3/src/libraries/core/GUIManager.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/libraries/core/GUIManager.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -127,9 +127,10 @@
         inline orxonox::PlayerInfo* getPlayer(const std::string& guiname) const { std::map<std::string, PlayerInfo*>::const_iterator it = this->players_.find(guiname); return (it != this->players_.end()) ? it->second : 0; } // tolua_export
 
         // 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 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 void addFontHelper(const std::string& name, int size, const std::string& fontName); // tolua_export
 
         static GUIManager& getInstance() { return Singleton<GUIManager>::getInstance(); } // tolua_export
 

Modified: code/branches/tutoriallevel3/src/libraries/network/synchronisable/Synchronisable.cc
===================================================================
--- code/branches/tutoriallevel3/src/libraries/network/synchronisable/Synchronisable.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/libraries/network/synchronisable/Synchronisable.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -382,7 +382,6 @@
 
   /**
    * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction)
-   * @param id gamestate id
    * @param mode Synchronisation mode (toclient, toserver or bidirectional)
    * @return true/false
    */
@@ -396,7 +395,6 @@
   
   /**
    * This function determines, wheter the object should accept data from the bytestream (according to its syncmode/direction)
-   * @param id gamestate id
    * @param mode Synchronisation mode (toclient, toserver or bidirectional)
    * @return true/false
    */

Modified: code/branches/tutoriallevel3/src/libraries/util/SubString.h
===================================================================
--- code/branches/tutoriallevel3/src/libraries/util/SubString.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/libraries/util/SubString.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -168,7 +168,7 @@
         inline bool empty() const { return this->tokens_.empty(); }
         /// Returns the number of tokens stored in this SubString
         inline unsigned int size() const { return this->tokens_.size(); }
-        /// Returns the i'th token from the subset of strings @param index The index of the requested doken
+        /// Returns the i'th token from the subset of strings @param index The index of the requested token
         inline const std::string& operator[](unsigned int index) const { return this->tokens_[index]; }
         /// Returns the i'th token from the subset of strings @param index The index of the requested token
         inline const std::string& getString(unsigned int index) const { return (*this)[index]; }

Modified: code/branches/tutoriallevel3/src/modules/notifications/CMakeLists.txt
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/CMakeLists.txt	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/CMakeLists.txt	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,8 +1,8 @@
 SET_SOURCE_FILES(NOTIFICATIONS_SRC_FILES
-  Notification.cc
   NotificationDispatcher.cc
   NotificationManager.cc
   NotificationQueue.cc
+  NotificationQueueCEGUI.cc
 )
 
 ADD_SUBDIRECTORY(dispatchers)
@@ -12,7 +12,7 @@
   FIND_HEADER_FILES
   TOLUA_FILES
     NotificationManager.h
-    NotificationQueue.h
+    NotificationQueueCEGUI.h
   PCH_FILE
     NotificationsPrecompiledHeaders.h
   LINK_LIBRARIES

Deleted: code/branches/tutoriallevel3/src/modules/notifications/Notification.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/Notification.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/Notification.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,77 +0,0 @@
-/*
- *   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 thes
- *   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 Notification.cc
-    @brief Implementation of the Notification class.
-*/
-
-#include "Notification.h"
-
-#include "core/CoreIncludes.h"
-#include "NotificationManager.h"
-
-namespace orxonox
-{
-
-    /**
-    @brief
-        Constructor. Creates a Notification with the input message and sender.
-    @param message
-        The message of the Notification.
-    @param sender
-        The sender of the Notification.
-    */
-    Notification::Notification(const std::string& message, const std::string& sender)
-    {
-        RegisterRootObject(Notification);
-        this->initialize();
-        this->message_ = message;
-        this->sender_ = sender;
-    }
-
-    /**
-    @brief
-        Destructor.
-    */
-    Notification::~Notification()
-    {
-
-    }
-
-    /**
-    @brief
-        Registers the object and sets some default values.
-    */
-    void Notification::initialize(void)
-    {
-        this->message_.clear();
-        this->sender_ = NotificationManager::NONE;
-    }
-
-}

Deleted: code/branches/tutoriallevel3/src/modules/notifications/Notification.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/Notification.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/Notification.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,88 +0,0 @@
-/*
- *   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 Notification.h
-    @brief Definition of the Notification class.
-    @ingroup Notifications
-*/
-
-#ifndef _Notification_H__
-#define _Notification_H__
-
-#include "notifications/NotificationsPrereqs.h"
-
-#include <string>
-#include "core/OrxonoxClass.h"
-
-namespace orxonox
-{
-
-    /**
-    @brief
-        A Notification represents a short message used to inform the player about something that just happened. With the @ref orxonox::NotificationManager "NotificationManager" a Notification can be sent from any part of orxonox and is then displayed by the proper @ref orxonox::NotificationQueue "NotificationQueue(s)" (depending on which senders the specific @ref orxonox::NotificationQueue "NotificationQueues" accepts).
-
-        A Notification is just a datastructure that is used internally by the Notifications module.
-
-    @author
-        Damian 'Mozork' Frick
-
-    @ingroup Notifications
-    */
-    class _NotificationsExport Notification : public OrxonoxClass
-    {
-        public:
-            Notification(const std::string& message, const std::string& sender);
-            virtual ~Notification();
-
-            /**
-            @brief Get the message of the Notification.
-            @return Returns the message of the Notification.
-            */
-            inline const std::string & getMessage(void) const
-                { return this->message_; }
-
-            /**
-            @brief Get the sender of the Notification.
-            @return Returns the sender of the Notification.
-            */
-            inline const std::string & getSender(void) const
-                { return this->sender_; }
-
-        private:
-            std::string message_; //!< The Notification message.
-            std::string sender_; //!< The sender of the notification.
-
-            void initialize(void); //!< Registers the object and sets some default values.
-            void registerVariables(void) {}
-
-    };
-
-}
-
-#endif /* _Notification_H__ */

Modified: code/branches/tutoriallevel3/src/modules/notifications/NotificationDispatcher.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationDispatcher.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationDispatcher.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -40,11 +40,10 @@
 #include "network/Host.h"
 
 #include "infos/PlayerInfo.h"
+#include "interfaces/NotificationListener.h"
 #include "interfaces/PlayerTrigger.h"
 #include "worldentities/pawns/Pawn.h"
 
-#include "NotificationManager.h"
-
 namespace orxonox
 {
 
@@ -60,7 +59,7 @@
     {
         RegisterObject(NotificationDispatcher);
 
-        this->sender_ = NotificationManager::NONE;
+        this->sender_ = NotificationListener::NONE;
         this->registerVariables();
     }
 
@@ -113,7 +112,8 @@
         if(GameMode::isStandalone() || Host::getPlayerID() == clientId || this->getSyncMode() == 0x0)
         {
             const std::string message = this->createNotificationMessage();
-            NotificationManager::sendNotification(message, clientId, this->getSender());
+            // TODO: Make the type configurable.
+            NotificationListener::sendNotification(message, this->getSender(), notificationMessageType::info, notificationSendMode::network, clientId);
         }
         else if(GameMode::isServer())
         {

Modified: code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -35,35 +35,19 @@
 
 #include "core/command/ConsoleCommand.h"
 #include "core/CoreIncludes.h"
-#include "core/GUIManager.h"
 #include "core/LuaState.h"
-#include "network/Host.h"
-#include "network/NetworkFunction.h"
 #include "util/ScopedSingletonManager.h"
 
 #include "interfaces/NotificationListener.h"
 
-#include "Notification.h"
 #include "NotificationQueue.h"
+#include "NotificationQueueCEGUI.h"
 
-#include "ToluaBindNotifications.h"
-
 namespace orxonox
 {
 
-    const std::string NotificationManager::ALL("all");
-    const std::string NotificationManager::NONE("none");
-
-    // Register tolua_open function when loading the library.
-    DeclareToluaInterface(Notifications);
-
     ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
 
-    // Setting console command to enter the edit mode.
-    SetConsoleCommand("enterEditMode", &NotificationManager::enterEditMode);
-
-    registerStaticNetworkFunction(NotificationManager::sendNotification);
-
     /**
     @brief
         Constructor. Registers the Object.
@@ -72,10 +56,6 @@
     {
         RegisterRootObject(NotificationManager);
 
-        this->highestIndex_ = 0;
-
-        ModifyConsoleCommand("enterEditMode").setObject(this);
-
         COUT(3) << "NotificatioManager created." << std::endl;
     }
 
@@ -85,8 +65,6 @@
     */
     NotificationManager::~NotificationManager()
     {
-        ModifyConsoleCommand("enterEditMode").setObject(NULL);
-
         // Destroys all Notifications.
         for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it!= this->allNotificationsList_.end(); it++)
             it->second->destroy();
@@ -105,7 +83,7 @@
         std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
         while(it != this->queues_.end())
         {
-            it->second->destroy(true);
+            it->second->destroy();
             it = this->queues_.begin();
         }
 
@@ -114,35 +92,77 @@
 
     /**
     @brief
-        Sends a Notification with the specified message to the specified client from the specified sender.
+        Creates and registers a Notification with the input message from the input sender.
+        This is called by the NotificationListener, whenever a new notification arrives.
     @param message
-        The message that should be sent.
-    @param clientId
-        The id of the client the notification should be sent to.
+        The message of the new Notification.
     @param sender
-        The sender that sent the notification.
-    @param isLocal
-        If this is set to true (false is default), then the Notification is sent to the client where this function is executed, meaning the Notification is sent locally.
+        The name of the entity (of the collective) that sent the new Notification.
+    @param type
+        The type of the new Notification.
+    @return
+        Returns true if successful.
     */
-    /*static*/ void NotificationManager::sendNotification(const std::string& message, unsigned int clientId, const std::string& sender, bool isLocal)
+    bool NotificationManager::registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
     {
-        // If we're in standalone mode or we're already no the right client we create and send the Notification.
-        if(GameMode::isStandalone() || isLocal || Host::getPlayerID() == clientId)
+        // TODO: Do something with the type.
+        Notification* notification = new Notification(message, sender, type);
+        return this->registerNotification(notification);
+    }
+
+    /**
+    @brief
+        Executes the input command from the input sender.
+        This is called by the NotificationListener, whenever a new command arrives.
+    @param command
+        The command to be executed,
+    @param sender
+        The The name of the entity (of the collective) that sent the command.
+    @return
+        Returns true if the command was successfully executed.
+    */
+    bool NotificationManager::executeCommand(notificationCommand::Value command, const std::string& sender)
+    {
+        bool commandExecuted = false;
+        if(command == notificationCommand::clear)
         {
-            Notification* notification = new Notification(message, sender);
-            if(NotificationManager::getInstance().registerNotification(notification))
-                COUT(3) << "Notification \"" << notification->getMessage() << "\" sent." << std::endl;
+            if(this->commandClear(sender))
+                commandExecuted = true;
         }
-        // If we're on the server (and the server is not the intended recipient of the Notification) we send it over the network.
-        else if(GameMode::isServer())
+
+        if(commandExecuted)
+            COUT(3) << "Notification command \"" << NotificationListener::command2Str(command) << "\" executed." << endl;
+
+        return commandExecuted;
+    }
+
+    /**
+    @brief
+        The clear command. Clears all NotificationQueues that have its sender as a target.
+    @param sender
+        The sender of the clear command.
+    @return
+        Returns true if the command was successfully executed by at least one NotificationQueue, false if it was not executed.
+    */
+    bool NotificationManager::commandClear(const std::string& sender)
+    {
+        bool all = (sender == NotificationListener::ALL);
+        bool executed = false;
+        // Clear all NotificationQueues that have the input sender as target.
+        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
         {
-            callStaticNetworkFunction(NotificationManager::sendNotification, clientId, message, clientId, sender);
+            const std::set<std::string>& set = it->second->getTargetsSet();
+            // If either the sender is 'all', the NotificationQueue has as target all or the NotificationQueue has the input sender as a target.
+            if(all || set.find(NotificationListener::ALL) != set.end() || set.find(sender) != set.end())
+                executed = it->second->tidy() || executed;
         }
+
+        return executed;
     }
-
+    
     /**
     @brief
-        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationListeners associated with its sender.
+        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationQueues associated with its sender.
     @param notification
         The Notification to be registered.
     @return
@@ -157,24 +177,23 @@
         // Add the Notification to the list that holds all Notifications.
         this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
 
-        if(notification->getSender() == NotificationManager::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
+        if(notification->getSender() == NotificationListener::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
             return true;
 
-        bool all = false;
-        if(notification->getSender() == NotificationManager::ALL) // If all are the sender, then the Notifications is added to every NotificationListener.
-            all = true;
+        // If all are the sender, then the Notifications is added to every NotificationQueue.
+        bool all = (notification->getSender() == NotificationListener::ALL);
 
-        // Insert the Notification in all NotificationListeners that have its sender as target.
-        for(std::map<NotificationListener*, unsigned int>::iterator it = this->listenerList_.begin(); it != this->listenerList_.end(); it++) // Iterate through all NotificationListeners.
+        // Insert the Notification in all NotificationQueues that have its sender as target.
+        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
         {
-            const std::set<std::string>& set = it->first->getTargetsSet();
-            bool bAll = set.find(NotificationManager::ALL) != set.end();
-            // If either the Notification has as sender 'all', the NotificationListener displays all Notifications or the NotificationListener has the sender of the Notification as target.
+            const std::set<std::string>& set = it->second->getTargetsSet();
+            bool bAll = set.find(NotificationListener::ALL) != set.end();
+            // If either the Notification has as sender 'all', the NotificationQueue displays all Notifications or the NotificationQueue has the sender of the Notification as target.
             if(all || bAll || set.find(notification->getSender()) != set.end())
             {
                 if(!bAll)
-                    this->notificationLists_[it->second]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationListener.
-                it->first->update(notification, time); // Update the NotificationListener.
+                    this->notificationLists_[it->second->getName()]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationQueue.
+                it->second->update(notification, time); // Update the NotificationQueue.
             }
         }
 
@@ -185,21 +204,21 @@
 
     /**
     @brief
-        Unregisters a Notification within the NotificationManager for a given NotificationListener.
+        Unregisters a Notification within the NotificationManager for a given NotificationQueue.
     @param notification
         A pointer to the Notification to be unregistered.
-    @param listener
-        A pointer to the NotificationListener the Notification is unregistered for.
+    @param queue
+        A pointer to the NotificationQueue the Notification is unregistered for.
     */
-    void NotificationManager::unregisterNotification(Notification* notification, NotificationListener* listener)
+    void NotificationManager::unregisterNotification(Notification* notification, NotificationQueue* queue)
     {
         assert(notification);
-        assert(listener);
+        assert(queue);
 
-        // Remove the Notification from the list of Notifications of the input NotificationListener.
-        this->removeNotification(notification, *(this->notificationLists_.find(this->listenerList_.find(listener)->second)->second));
+        // Remove the Notification from the list of Notifications of the input NotificationQueue.
+        this->removeNotification(notification, *(this->notificationLists_.find(queue->getName())->second));
 
-        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from listener (&" << listener << ")" << std::endl;
+        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from NotificationQueue " << queue->getName() << "." << std::endl;
     }
 
     /**
@@ -229,65 +248,123 @@
 
     /**
     @brief
-        Registers a NotificationListener within the NotificationManager.
-    @param listener
-        The NotificationListener to be registered.
+        Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
+    @param queue
+        The NotificationQueue the Notifications are fetched for.
+    @param map
+        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
+    @param timeFrameStart
+        The start time of the timeframe.
+    @param timeFrameEnd
+        The end time of the timeframe.
     @return
-        Returns true if successful.  Fales if the NotificationListener is already registered.
+        Returns true if successful.
     */
-    bool NotificationManager::registerListener(NotificationListener* listener)
+    void NotificationManager::getNotifications(NotificationQueue* queue, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
     {
-        assert(listener);
+        assert(queue);
+        assert(map);
 
-        // If the NotificationListener is already registered.
-        if(this->listenerList_.find(listener) != this->listenerList_.end())
+        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
+
+        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
+        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
+        itLowest = notifications->lower_bound(timeFrameStart);
+        itHighest = notifications->upper_bound(timeFrameEnd);
+
+        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
+            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
+    }
+
+    /**
+    @brief
+        Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
+    @param queue
+        The NotificationQueue the Notifications are fetched for.
+    @param map
+        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
+    @param numberOfNotifications
+        The number of newest Notifications to be got.
+    @return
+        Returns true if successful.
+    */
+    void NotificationManager::getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications)
+    {
+        assert(queue);
+        assert(map);
+
+        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
+
+        if(!notifications->empty()) // If the list of Notifications is not empty.
+        {
+            std::multimap<std::time_t,Notification*>::iterator it = notifications->end();
+            for(int i = 0; i < numberOfNotifications; i++) // Iterate through the Notifications from the newest until we have the specified number of notifications.
+            {
+                it--;
+                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
+                if(it == notifications->begin())
+                    break;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Registers a NotificationQueue.
+        This makes sure that the NotificationQueue can be accessed through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
+    @param queue
+        A pointer to the NotificationQueue to be registered.
+    @return
+        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
+    */
+    bool NotificationManager::registerQueue(NotificationQueue* queue)
+    {
+        assert(queue);
+
+        // If the NotificationQueue is already registered.
+        if(this->queues_.find(queue->getName()) != this->queues_.end())
             return false;
 
-        this->highestIndex_ += 1;
-        unsigned int index = this->highestIndex_; // An identifier that identifies each registered NotificationListener uniquely.
+        this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)); // Add the NotificationQueue to the list of NotificationQueues.
 
-        this->listenerList_[listener] = index; // Add the NotificationListener to the list of NotificationListeners.
+        const std::set<std::string>& set = queue->getTargetsSet();
 
-        const std::set<std::string>& set = listener->getTargetsSet();
-
-        // If all senders are the target of the NotificationListener, then the list of Notifications for that specific NotificationListener is the same as the list of all Notifications.
-        bool bAll = set.find(NotificationManager::ALL) != set.end();
+        // If all senders are the target of the NotificationQueue, then the list of Notifications for that specific NotificationQueue is the same as the list of all Notifications.
+        bool bAll = set.find(NotificationListener::ALL) != set.end();
         std::multimap<std::time_t, Notification*>* map = NULL;
         if(bAll)
-            this->notificationLists_[index] = &this->allNotificationsList_;
-        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationListeners.
+            this->notificationLists_[queue->getName()] = &this->allNotificationsList_;
+        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationQueues.
         else
         {
-            this->notificationLists_[index] = new std::multimap<std::time_t, Notification*>;
-            map = this->notificationLists_[index];
+            this->notificationLists_[queue->getName()] = new std::multimap<std::time_t, Notification*>;
+            map = this->notificationLists_[queue->getName()];
         }
 
-        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationListener.
+        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationQueue.
         for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
         {
             if(!bAll && set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
                 map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
         }
 
-        listener->update(); // Update the listener.
-
-        COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
-
+        queue->update(); // Update the queue.
+        
+        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
         return true;
     }
 
     /**
     @brief
-        Unregisters a NotificationListener within the NotificationManager.
-    @param listener
-        The NotificationListener to be unregistered.
+        Unregisters a NotificationQueue.
+    @param queue
+        A pointer to the NotificationQueue to be unregistered.
     */
-    void NotificationManager::unregisterListener(NotificationListener* listener)
+    void NotificationManager::unregisterQueue(NotificationQueue* queue)
     {
-        assert(listener);
+        assert(queue);
 
-        unsigned int identifier = this->listenerList_.find(listener)->second;
-        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(identifier)->second;
+        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(queue->getName())->second;
 
         // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
         std::multimap<std::time_t, Notification*>::iterator it = map->begin();
@@ -295,128 +372,93 @@
         {
             while(it != map->end())
             {
-                this->unregisterNotification(it->second, listener);
+                this->unregisterNotification(it->second, queue);
                 it = map->begin();
             }
             delete map;
         }
 
-        COUT(4) << "NotificationListener '" << identifier << "' unregistered with the NotificationManager." << std::endl;
-
-        // Remove the NotificationListener from the list of NotificationListeners.
-        this->listenerList_.erase(listener);
-        // Remove the Notifications list that was associated with the input NotificationListener.
-        this->notificationLists_.erase(identifier);
+        // Remove the NotificationQueue from the list of NotificationQueues.
+        this->queues_.erase(queue->getName());
+        // Remove the Notifications list that was associated with the input NotificationQueue.
+        this->notificationLists_.erase(queue->getName());
+        
+        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
     }
 
     /**
     @brief
-        Fetches the Notifications for a specific NotificationListener in a specified timeframe and stores them in the input map.
-    @param listener
-        The NotificationListener the Notifications are fetched for.
-    @param map
-        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
-    @param timeFrameStart
-        The start time of the timeframe.
-    @param timeFrameEnd
-        The end time of the timeframe.
+        Get the NotificationQueue with the input name.
+    @param name
+        The name of the NotificationQueue.
     @return
-        Returns true if successful.
+        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
     */
-    void NotificationManager::getNotifications(NotificationListener* listener, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
+    NotificationQueue* NotificationManager::getQueue(const std::string & name)
     {
-        assert(listener);
-        assert(map);
+        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
+        // Returns NULL if no such NotificationQueue exists.
+        if(it == this->queues_.end())
+            return NULL;
 
-        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[this->listenerList_[listener]]; // All the Notifications for the input NotificationListener.
-
-        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
-        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
-        itLowest = notifications->lower_bound(timeFrameStart);
-        itHighest = notifications->upper_bound(timeFrameEnd);
-
-        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
-            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
+        return (*it).second;
     }
 
     /**
     @brief
-        Enters the edit mode of the NotificationLayer.
+        Loads all the NotificationQueues that should exist.
     */
-    void NotificationManager::enterEditMode(void)
+    void NotificationManager::loadQueues(void)
     {
-        if(GameMode::showsGraphics())
-        {
-            GUIManager::getInstance().hideGUI("NotificationLayer");
-            GUIManager::getInstance().showGUI("NotificationLayer", false, false);
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.enterEditMode()");
-        }
+        NotificationQueueCEGUI* allQueue = new NotificationQueueCEGUI("all");
+        allQueue->setDisplaySize(Vector2(0.5, 0));
+        allQueue->setPosition(Vector4(0.0, 10, 0.3, 0));
+
+        NotificationQueueCEGUI* infoQueue = new NotificationQueueCEGUI("info", "gameinfo", 1, -1);
+        infoQueue->setPosition(Vector4(0.2, 0, 0.8, 0));
+        infoQueue->setFontSize(24);
+        infoQueue->setFontColor(Vector4(1.0, 1.0, 0.0, 0.8));
+        infoQueue->setAlignment("HorzCentred");
+        infoQueue->setDisplaySize(Vector2(0.6, 0.0));
     }
 
+    // Notification class
+
     /**
     @brief
-        Registers a NotificationQueue.
-        This makes sure that the NotificationQueue can be attained through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
-    @param queue
-        A pointer to the NotificationQueue to be registered.
-    @return
-        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
-    */
-    bool NotificationManager::registerQueue(NotificationQueue* queue)
-    {
-        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
-        return this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)).second;
-    }
+        Constructor. Creates a Notification with the input message and sender.
+    @param message
+        The message of the Notification.
+    @param sender
+        The sender of the Notification.
+    @param type
 
-    /**
-    @brief
-        Unregisters a NotificationQueue.
-    @param queue
-        A pointer to the NotificationQueue to be unregistered.
     */
-    void NotificationManager::unregisterQueue(NotificationQueue* queue)
+    Notification::Notification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
     {
-        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
-        this->queues_.erase(queue->getName());
+        this->initialize();
+        this->message_ = message;
+        this->sender_ = sender;
+        this->type_ = type;
     }
 
     /**
     @brief
-        Loads all the NotificationQueues that should exist.
+        Destructor.
     */
-    void NotificationManager::loadQueues(void)
+    Notification::~Notification()
     {
-        new NotificationQueue("all");
-    }
 
-    /**
-    @brief
-        Creates a new NotificationQueue.
-        This is used in lua.
-    @param name
-        The name of the new NotificationQueue.
-    */
-    void NotificationManager::createQueue(const std::string& name)
-    {
-        new NotificationQueue(name);
     }
 
     /**
     @brief
-        Get the NotificationQueue with the input name.
-    @param name
-        The name of the NotificationQueue.
-    @return
-        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
+        Registers the object and sets some default values.
     */
-    NotificationQueue* NotificationManager::getQueue(const std::string & name)
+    void Notification::initialize(void)
     {
-        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
-        // Returns NULL if no such NotificationQueue exists.
-        if(it == this->queues_.end())
-            return NULL;
-
-        return (*it).second;
+        this->message_.clear();
+        this->sender_ = NotificationListener::NONE;
     }
 
 }

Modified: code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationManager.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -41,32 +41,86 @@
 #include <map>
 #include <string>
 
+#include "core/OrxonoxClass.h"
 #include "util/Singleton.h"
-#include "core/OrxonoxClass.h"
+#include "interfaces/NotificationListener.h"
 
 namespace orxonox // tolua_export
 { // tolua_export
 
     /**
     @brief
-        The Singleton NotificationManager functions as a gateway between @ref orxonox::Notification "Notifications" and @ref orxonox::NotificationListener "NotificationListeners".
-        It receives, organizes @ref orxonox::Notification "Notifications" and the redistributes them to the specific @ref orxonox::NotificationListener "NotificationListeners".
-        It also provides a static function to send @ref orxonox::Notification "Notifications" and works as a liaison between the @ref orxonox::NotificationQueue "NotificationQueues" and the GUI that displays notification, called NotificationLayer.
+        A Notification represents a short message used to inform the player about something that just happened. With the @ref orxonox::NotificationManager "NotificationManager" a Notification can be sent from any part of orxonox and is then displayed by the proper @ref orxonox::NotificationQueue "NotificationQueue(s)" (depending on which senders the specific @ref orxonox::NotificationQueue "NotificationQueues" accepts).
 
+        A Notification is just a data structure that is used internally by the Notifications module.
+
     @author
         Damian 'Mozork' Frick
 
     @ingroup Notifications
     */
+    class _NotificationsExport Notification
+    {
+        public:
+            Notification(const std::string& message, const std::string& sender, notificationMessageType::Value type);
+            virtual ~Notification();
+
+            /**
+            @brief Destroys the Notification.
+            */
+            void destroy(void)
+                { delete this; }
+
+            /**
+            @brief Get the message of the Notification.
+            @return Returns the message of the Notification.
+            */
+            inline const std::string & getMessage(void) const
+                { return this->message_; }
+
+            /**
+            @brief Get the sender of the Notification.
+            @return Returns the sender of the Notification.
+            */
+            inline const std::string & getSender(void) const
+                { return this->sender_; }
+
+            /**
+            @brief Get the type of the Notification.
+            @return Returns an enum with the type of the Notification.
+            */
+            inline notificationMessageType::Value getType(void) const
+                { return this->type_; }
+
+        private:
+            std::string message_; //!< The Notification message.
+            std::string sender_; //!< The sender of the notification.
+            notificationMessageType::Value type_; //!< The type of the notification.
+
+            void initialize(void); //!< Registers the object and sets some default values.
+
+    };
+
+    /**
+    @brief
+        The Singleton NotificationManager is a NotificationListener and functions as a gateway between @ref orxonox::Notification "Notifications" and @ref orxonox::NotificationQueue "NotificationQueues".
+        It receives, organizes @ref orxonox::Notification "Notifications" and the redistributes them to the specific @ref orxonox::NotificationQueue "NotificationQueues".
+        It also works as a liaison between the @ref orxonox::NotificationQueue "NotificationQueues" and the GUI that displays notification, called NotificationLayer.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Notifications
+    */
     class _NotificationsExport NotificationManager // tolua_export
-        : public Singleton<NotificationManager>, public OrxonoxClass
+        : public Singleton<NotificationManager>, public NotificationListener
     { // tolua_export
             friend class Singleton<NotificationManager>;
         public:
             NotificationManager();
             virtual ~NotificationManager();
 
-            virtual void preDestroy(void); //!< Is called before the object is destroyed.
+            virtual void preDestroy(void); // Is called before the object is destroyed.
 
             /**
             @brief Get the instance of the NotificationManager Singleton.
@@ -74,52 +128,45 @@
             */
             static NotificationManager& getInstance() { return Singleton<NotificationManager>::getInstance(); } // tolua_export
 
-            static const std::string ALL; //!< Static string to indicate a sender that sends to all NotificationListeners.
-            static const std::string NONE; //!< Static string to indicare a sender that sends to no specific NotificationListener.
+            virtual bool registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type);
+            virtual bool executeCommand(notificationCommand::Value command, const std::string& sender);
 
-            //! Sends a Notification with the specified message to the specified client from the specified sender.
-            static void sendNotification(const std::string& message, unsigned int clientId, const std::string& sender = NotificationManager::NONE, bool isLocal = false);
+            bool registerNotification(Notification* notification); // Registers a Notification within the NotificationManager.
+            void unregisterNotification(Notification* notification, NotificationQueue* queue); // Unregisters a Notification within the NotificationManager for a given NotificationQueue.
 
-            bool registerNotification(Notification* notification); //!< Registers a Notification within the NotificationManager.
-            void unregisterNotification(Notification* notification, NotificationListener* listener); //!< Unregisters a Notification within the NotificationManager for a given NotificationListener.
-            bool registerListener(NotificationListener* listener); //!< Registers a NotificationListener within the NotificationManager.
-            void unregisterListener(NotificationListener* listener); //!< Unregisters a NotificationListener withing the NotificationManager.
+            void getNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd); // Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
 
-            void getNotifications(NotificationListener* listener, std::multimap<std::time_t, Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd); //!< Fetches the Notifications for a specific NotificationListener in a specified timeframe and stores them in the input map.
-
             /**
-            @brief Fetches the Notifications for a specific NotificationListener in a timeframe from now-timeDelay to now and stores them in the input map.
-            @param listener The NotificationListener the Notifications are fetched for.
+            @brief Fetches the Notifications for a specific NotificationQueue in a timeframe from (now-timeDelay) to now and stores them in the input map.
+            @param queue The NotificationQueue the Notifications are fetched for.
             @param map A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
             @param timeDelay The timespan.
             @return Returns true if successful.
             */
-            void getNotifications(NotificationListener* listener, std::multimap<std::time_t, Notification*>* map, int timeDelay)
-                { this->getNotifications(listener, map, std::time(0)-timeDelay, std::time(0)); }
+            void getNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int timeDelay)
+                { this->getNotifications(queue, map, std::time(0)-timeDelay, std::time(0)); }
 
-            void enterEditMode(void); //!< Enters the edit mode of the NotificationLayer.
+            void getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications); // Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
 
-            bool registerQueue(NotificationQueue* queue); //!< Registers a NotificationQueue.
-            void unregisterQueue(NotificationQueue* queue); //!< Unregisters a NotificationQueue.
+            bool registerQueue(NotificationQueue* queue); // Registers a NotificationQueue.
+            void unregisterQueue(NotificationQueue* queue); // Unregisters a NotificationQueue.
 
-            // tolua_begin
-            void loadQueues(void); //!< Loads all the NotificationQueues that should exist.
-            void createQueue(const std::string& name); //!< Creates a new NotificationQueue.
-            orxonox::NotificationQueue* getQueue(const std::string & name); //!< Get the NotificationQueue with the input name.
-            // tolua_end
+            void loadQueues(void); // tolua_export // Loads all the NotificationQueues that should exist.
 
+            NotificationQueue* getQueue(const std::string & name); // Get the NotificationQueue with the input name.
+
         private:
             static NotificationManager* singletonPtr_s;
 
-            unsigned int highestIndex_; //!< This variable holds the highest index (resp. key) in notificationLists_s, to secure that no key appears twice.
-
             std::multimap<std::time_t, Notification*> allNotificationsList_; //!< Container where all Notifications are stored.
-            std::map<NotificationListener*, unsigned int> listenerList_; //!< Container where all NotificationListeners are stored with a number as identifier.
-            std::map<int,std::multimap<std::time_t, Notification*>*> notificationLists_; //!< Container where all Notifications, for each identifier (associated with a NotificationListener), are stored.
+            std::map<const std::string, std::multimap<std::time_t, Notification*>*> notificationLists_; //!< Container where all Notifications, for each identifier (associated with a NotificationQueue), are stored.
 
             std::map<const std::string, NotificationQueue*> queues_; //!< The list of NotificationQueues created by the NotificationManager.
 
-            bool removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map); //!< Helper method that removes an input Notification form an input map.
+            bool removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map); // Helper method that removes an input Notification form an input map.
+            
+            // Commands
+            bool commandClear(const std::string& sender); // The clear command. Clears all NotificationQueues that have its sender as a target.
 
     }; // tolua_export
 

Modified: code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -37,14 +37,8 @@
 #include <sstream>
 
 #include "core/CoreIncludes.h"
-#include "core/GameMode.h"
-#include "core/GUIManager.h"
-#include "core/LuaState.h"
-#include "util/Convert.h"
 #include "util/SubString.h"
 
-#include "Notification.h"
-
 namespace orxonox
 {
 
@@ -55,7 +49,7 @@
         The name of the new NotificationQueue. It needs to be unique
     @param senders
         The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
-        The senders need to be seperated by commas.
+        The senders need to be separated by commas.
     @param size
         The size (the maximum number of displayed Notifications) of this NotificationQueue.
     @param displayTime
@@ -87,21 +81,6 @@
             return;
         }
 
-        this->create(); // Creates the NotificationQueue in lua.
-
-        // Register the NotificationQueue as NotificationListener with the NotificationManager.
-        bool listenerRegistered = NotificationManager::getInstance().registerListener(this);
-        if(!listenerRegistered) // If the registration has failed.
-        {
-            this->registered_ = false;
-            // Remove the NotificationQueue in lua.
-            if(GameMode::showsGraphics())
-                GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
-            NotificationManager::getInstance().unregisterQueue(this);
-            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
-            return;
-        }
-
         COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
     }
 
@@ -118,41 +97,14 @@
             this->clear(true);
 
             // Unregister with the NotificationManager.
-            NotificationManager::getInstance().unregisterListener(this);
             NotificationManager::getInstance().unregisterQueue(this);
         }
-    }
-
-    /**
-    @brief
-        Destroys the NotificationQueue.
-        Used in lua and NotificationManager.
-    @param noGraphics
-        If this is set to true (false is default), then the queue is not removed in lua. This is used to destroy the queue, after the GUIManager has been destroyed.
-    */
-    void NotificationQueue::destroy(bool noGraphics)
-    {
-        // Remove the NotificationQueue in lua.
-        if(GameMode::showsGraphics() && !noGraphics)
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
-
+        
         COUT(3) << "NotificationQueue '" << this->getName() << "' destroyed." << std::endl;
-
-        this->OrxonoxClass::destroy();
     }
 
     /**
     @brief
-        Creates the NotificationQueue in lua.
-    */
-    void NotificationQueue::create(void)
-    {
-        if(GameMode::showsGraphics())
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
-    }
-
-    /**
-    @brief
         Updates the queue from time to time.
     @param dt
         The time interval that has passed since the last tick.
@@ -160,7 +112,7 @@
     void NotificationQueue::tick(float dt)
     {
         this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
-        if(this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
+        if(this->displayTime_ != INF && this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
         {
             this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time.
 
@@ -180,6 +132,7 @@
     @brief
         Updates the NotificationQueue.
         Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
+        This is called by the NotificationManager when the Notifications have changed so much, that the NotificationQueue may have to re-initialize his operations.
     */
     void NotificationQueue::update(void)
     {
@@ -187,7 +140,10 @@
 
         std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
         // Get the Notifications sent in the interval from now to now minus the display time.
-        NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
+        if(this->displayTime_ == INF)
+            NotificationManager::getInstance().getNewestNotifications(this, notifications, this->getMaxSize());
+        else
+            NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
 
         if(!notifications->empty())
         {
@@ -245,11 +201,11 @@
         // Insert the Notification at the begin of the list (vector, actually).
         this->notifications_.insert(this->notifications_.begin(), container);
 
-        // Push the Notification to the GUI.
-        if(GameMode::showsGraphics())
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
+        // Inform that a Notification was pushed.
+        this->notificationPushed(notification);
 
         COUT(5) << "Notification \"" << notification->getMessage() << "\" pushed to NotificationQueue '" << this->getName() << "'" << endl;
+        COUT(3) << "NotificationQueue \"" << this->getName() << "\": " << notification->getMessage() << endl;
     }
 
     /**
@@ -278,9 +234,8 @@
 
         delete container;
 
-        // Pops the Notification from the GUI.
-        if(GameMode::showsGraphics())
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.popNotification(\"" + this->getName() + "\")");
+        // Inform that a Notification was popped.
+        this->notificationPopped();
     }
 
     /**
@@ -304,16 +259,16 @@
 
         delete *containerIterator;
 
-        // Removes the Notification from the GUI.
-        if(GameMode::showsGraphics())
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
+        // TODO: index automatically cast?
+        // Inform that a Notification was removed.
+        this->notificationRemoved(index);
     }
 
     /**
     @brief
         Clears the NotificationQueue by removing all NotificationContainers.
     @param noGraphics
-        If this is eset to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
+        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
     */
     void NotificationQueue::clear(bool noGraphics)
     {
@@ -325,10 +280,6 @@
 
         this->notifications_.clear();
         this->size_ = 0;
-
-        // Clear the NotificationQueue in the GUI.
-        if(GameMode::showsGraphics() && !noGraphics)
-            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.clearQueue(\"" + this->getName() + "\")");
     }
 
     /**
@@ -363,11 +314,9 @@
     @brief
         Sets the maximum number of seconds a Notification is displayed.
     @param time
-        The number of seconds the Notifications is displayed.
-    @return
-        Returns true if successful.
+        The number of seconds a Notification is displayed.
     */
-    void NotificationQueue::setDisplayTime(unsigned int time)
+    void NotificationQueue::setDisplayTime(int time)
     {
         if(this->displayTime_ == time)
             return;
@@ -380,7 +329,7 @@
 
     /**
     @brief
-        Produces all targets of the NotificationQueue concatinated as string, with commas (',') as seperators.
+        Produces all targets of the NotificationQueue concatenated as string, with commas (',') as separators.
     @return
         Returns the targets as a string.
     */
@@ -406,7 +355,7 @@
         Sets the targets of the NotificationQueue.
         The targets are the senders whose Notifications are displayed in this queue.
     @param targets
-        Accepts a string of targets, each seperated by commas (','), spaces are ignored.
+        Accepts a string of targets, each separated by commas (','), spaces are ignored.
     */
     void NotificationQueue::setTargets(const std::string & targets)
     {
@@ -416,12 +365,26 @@
         for(unsigned int i = 0; i < string.size(); i++)
             this->targets_.insert(string[i]);
 
+        // TODO: Why?
         if(this->registered_)
         {
-            NotificationManager::getInstance().unregisterListener(this);
-            NotificationManager::getInstance().registerListener(this);
+            NotificationManager::getInstance().unregisterQueue(this);
+            NotificationManager::getInstance().registerQueue(this);
         }
     }
 
+    /**
+    @brief
+        Pops all Notifications from the NotificationQueue.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool NotificationQueue::tidy(void)
+    {
+        while(this->size_ > 0)
+            this->pop();
+        return true;
+    }
+
 }
 

Modified: code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -45,10 +45,9 @@
 #include "NotificationManager.h"
 
 #include "tools/interfaces/Tickable.h"
-#include "interfaces/NotificationListener.h"
 
-namespace orxonox // tolua_export
-{ // tolua_export
+namespace orxonox
+{
 
     /**
     @brief
@@ -77,7 +76,7 @@
     @brief
         Displays @ref orxonox::Notification "Notifications" from specific senders.
 
-        There are quite some parameters that influence the behaviour of the NotificationQueue:
+        There are quite some parameters that influence the behavior of the NotificationQueue:
         - @b name The name of the NotificationQueue. It needs to be unique.
         - @b senders The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
         - @b size The size of the NotificationQueue, it specifies how many @ref orxonox::Notification "Notifications" are displayed at once at the most.
@@ -88,17 +87,13 @@
 
     @ingroup Notifications
     */
-    class _NotificationsExport NotificationQueue // tolua_export
-        : public Tickable, public NotificationListener
-    { // tolua_export
+    class _NotificationsExport NotificationQueue : public Tickable
+    {
 
         public:
-            NotificationQueue(const std::string& name, const std::string& senders = NotificationManager::ALL, unsigned int size = NotificationQueue::DEFAULT_SIZE, unsigned int displayTime = NotificationQueue::DEFAULT_DISPLAY_TIME);
+            NotificationQueue(const std::string& name, const std::string& senders = NotificationListener::ALL, unsigned int size = NotificationQueue::DEFAULT_SIZE, unsigned int displayTime = NotificationQueue::DEFAULT_DISPLAY_TIME);
             virtual ~NotificationQueue();
 
-            //! Destroys the NotificationQueue.
-            void destroy(bool noGraphics = false); // tolua_export
-
             virtual void tick(float dt); //!< To update from time to time.
 
             void update(void); //!< Updates the NotificationQueue.
@@ -120,12 +115,12 @@
             inline unsigned int getMaxSize() const
                 { return this->maxSize_; }
 
-            void setDisplayTime(unsigned int time); //!< Sets the maximum number of seconds a Notification is displayed.
+            void setDisplayTime(int time); //!< Sets the maximum number of seconds a Notification is displayed.
             /**
             @brief Returns the time interval the Notification is displayed.
             @return Returns the display time.
             */
-            inline unsigned int getDisplayTime() const
+            inline int getDisplayTime() const
                 { return this->displayTime_; }
             // tolua_end
 
@@ -143,20 +138,40 @@
             inline const std::set<std::string> & getTargetsSet()
                 { return this->targets_; }
 
-            // tolua_begin
             void setTargets(const std::string & targets); //!< Set the targets of this NotificationQueue.
-            const std::string& getTargets(void) const; //!< Returns a string consisting of the concatination of the targets.
-            // tolua_end
+            const std::string& getTargets(void) const; //!< Returns a string consisting of the concatenation of the targets.
 
-        private:
+            bool tidy(void); // Pops all Notifications from the NotificationQueue.
+            
+        protected:
+            /**
+            @brief Is called when a notification was pushed.
+            @param notification The Notification that was pushed.
+            */
+            virtual void notificationPushed(Notification* notification) {}
+            /**
+            @brief Is called when a notification was popped.
+            */
+            virtual void notificationPopped(void) {}
+            /**
+            @brief Is called when a notification was removed.
+            @param index The index the removed notification was at.
+            */
+            virtual void notificationRemoved(unsigned int index) {}
+            
+            virtual void clear(bool noGraphics = false); //!< Clears the NotificationQueue by removing all NotificationContainers.
+
+        protected:
             static const unsigned int DEFAULT_SIZE = 5; //!< The default maximum number of Notifications displayed.
             static const unsigned int DEFAULT_DISPLAY_TIME = 30; //!< The default display time.
+            static const int INF = -1; //!< Constant denoting infinity.
 
+        private:
             std::string name_; //!< The name of the NotificationQueue.
 
             unsigned int maxSize_; //!< The maximal number of Notifications displayed.
             unsigned int size_; //!< The number of Notifications displayed.
-            unsigned int displayTime_; //!< The time a Notification is displayed.
+            int displayTime_; //!< The time a Notification is displayed.
 
             bool registered_; //!< Helper variable to remember whether the NotificationQueue is registered already.
 
@@ -168,18 +183,14 @@
             float tickTime_; //!< Helper variable, to not have to check for Notifications that have been displayed too long, every tick.
             NotificationContainer timeLimit_; //!< Helper object to check against to determine whether Notifications have expired.
 
-            void create(void); //!< Creates the NotificationQueue in lua.
-
             void setName(const std::string& name); //!< Sets the name of the NotificationQueue.
 
             void push(Notification* notification, const std::time_t & time); //!< Adds (pushes) a Notification to the NotificationQueue.
             void pop(void); //!< Removes (pops) the least recently added Notification form the NotificationQueue.
             void remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator); //!< Removes the Notification that is stored in the input NotificationContainer.
 
-            void clear(bool noGraphics = false); //!< Clears the NotificationQueue by removing all NotificationContainers.
+    };
 
-    }; // tolua_export
+}
 
-} // tolua_export
-
-#endif /* _NotificationOverlay_H__ */
+#endif /* _NotificationQueue_H__ */

Copied: code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.cc (from rev 8452, code/branches/tutoriallevel2/src/modules/notifications/NotificationQueueCEGUI.cc)
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.cc	                        (rev 0)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -0,0 +1,273 @@
+/*
+ *   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 NotificationQueueCEGUI.cc
+    @brief Implementation of the NotificationQueueCEGUI class.
+*/
+
+#include "NotificationQueueCEGUI.h"
+
+#include <sstream>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/GUIManager.h"
+#include "core/LuaState.h"
+#include "util/Convert.h"
+
+#include "ToluaBindNotifications.h"
+
+namespace orxonox
+{
+
+    // Register tolua_open function when loading the library.
+    DeclareToluaInterface(Notifications);
+
+    /*static*/ const std::string NotificationQueueCEGUI::NOTIFICATION_LAYER("NotificationLayer");
+
+    NotificationQueueCEGUI::NotificationQueueCEGUI(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime) : NotificationQueue(name, senders, size, displayTime)
+    {
+        RegisterObject(NotificationQueueCEGUI);
+
+        this->displaySize_ = Vector4(1.0, 0.0, 0.0, 0.0);
+        this->position_ = Vector4(0.0, 0.0, 0.0, 0.0);
+        this->alignment_ = "LeftAligned";
+        this->fontSize_ = 12;
+        this->fontColor_ = Vector4(1.0, 1.0, 1.0, 1.0);
+        this->fontColorStr_ = "FFFFFFFF";
+        
+        // Create the NotificationQueueCEGUI in lua.
+        this->create();
+    }
+    
+    NotificationQueueCEGUI::~NotificationQueueCEGUI()
+    {
+        
+    }
+
+    /**
+    @brief
+        Destroys the NotificationQueueCEGUI.
+        Used in lua and NotificationManager.
+    @param noGraphics
+        If this is set to true (false is default), then the queue is not removed in lua. This is used to destroy the queue, after the GUIManager has been destroyed.
+    */
+    void NotificationQueueCEGUI::destroy(bool noGraphics)
+    {
+        // Remove the NotificationQueue in lua.
+        if(GameMode::showsGraphics() && !noGraphics)
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeQueue(\"" + this->getName() +  "\")");
+
+        NotificationQueue::destroy();
+    }
+
+    /**
+    @brief
+        Set the size of the window that displays the NotificationQueue.
+    @param size
+        The size is a vector with components:
+        - The relative width of the window. (A value between 0 and 1)
+        - The absolute width in pixels. (Additional to the relative width, can be negative)
+        - The relative height of the window. (A value between 0 and 1)
+        - The absolute height in pixels. (Additional to the relative width, can be negative.)
+        If both the 3rd and 4th component of size are set to 0 the height is set such that exactly as many Notifications fit as is the maximum size of the NotificationQueue (in terms of the number of Notifications).
+    */
+    void NotificationQueueCEGUI::setDisplaySize(const Vector4& size)
+    {
+        if(this->displaySize_ == size)
+            return;
+
+        if(size.x < 0.0 || size.x > 1.0 || size.z < 0.0 || size.z > 1.0)
+        {
+            COUT(2) << "The display size of the NotificationQueueCEGUI " << this->getName() << " was trying to be set, but the relative size was not in [0,1]. Aborting..." << endl;
+            return;
+        }
+
+        this->displaySize_ = size;
+        if(size.z == 0.0 && size.w == 0.0)
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".resizeQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->displaySize_.x) + ", " + multi_cast<std::string>(this->displaySize_.y) + ")");
+        else
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".resizeQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->displaySize_.x) + ", " + multi_cast<std::string>(this->displaySize_.y) + ", " + multi_cast<std::string>(this->displaySize_.z) + ", " + multi_cast<std::string>(this->displaySize_.w) + ")");
+    }
+
+    /**
+    @brief
+        Set the position of the window that displays the NotificationQueue.
+    @param position
+        The position is a vector with components:
+        - The relative x-position of the window. (A value between 0 and 1)
+        - The absolute x-position in pixels. (Additional to the relative x-position, can be negative)
+        - The relative y-position of the window. (A value between 0 and 1)
+        - The absolute y-position in pixels. (Additional to the relative y-position, can be negative.)
+    */
+    void NotificationQueueCEGUI::setPosition(const Vector4& position)
+    {
+        if(this->position_ == position)
+            return;
+
+        if(position.x < 0.0 || position.x > 1.0 || position.z < 0.0 || position.z > 1.0)
+        {
+            COUT(2) << "The position the NotificationQueueCEGUI " << this->getName() << " was trying to be set, but the relative position was not in [0,1]. Aborting..." << endl;
+            return;
+        }
+
+        this->position_ = position;
+        GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".moveQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->position_.x) + ", " + multi_cast<std::string>(this->position_.y) + ", " + multi_cast<std::string>(this->position_.z) + ", " + multi_cast<std::string>(this->position_.w) + ")");
+    }
+
+    /**
+    @brief
+        Set the horizontal alignment of the Notifications text.
+    @param alignment
+        The alignment of the Notifications, they are the possible string that the CEGUI Falagard StaticText HorzFormatting property can take.
+    @see http://cegui.org.uk/api_reference/classCEGUI_1_1FalagardStaticTextProperties_1_1HorzFormatting.html
+    */
+    void NotificationQueueCEGUI::setAlignment(const std::string& alignment)
+    {
+        if(this->alignment_ == alignment)
+            return;
+
+        // TODO: Check whether the alignment string is correct?
+        this->alignment_ = alignment;
+        GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueAlignment(\"" + this->getName() + "\", \"" + this->alignment_ + "\")");
+    }
+
+    /**
+    @brief
+        Set the font size of the text displayed by this NotificationQueue.
+    @param size
+        The font size.
+    */
+    void NotificationQueueCEGUI::setFontSize(unsigned int size)
+    {
+        if(this->fontSize_ == size)
+            return;
+
+        this->fontSize_ = size;
+        GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueFontSize(\"" + this->getName() + "\", " + multi_cast<std::string>(this->fontSize_) + ")");
+    }
+
+    /**
+    @brief
+        Set the font color if the text displayed by this NotificationQueue.
+    @param color
+        The color is a vector with the components being RGBA and taking values from 0 to 1.
+    */
+    void NotificationQueueCEGUI::setFontColor(const Vector4& color)
+    {
+        if(this->fontColor_ == color)
+            return;
+
+        this->fontColor_ = color;
+        // Convert to ARGB format.
+        std::stringstream stream;
+        for(unsigned int i = 0; i < 4; i++)
+            stream << std::hex << std::setw(2) << std::setfill('0') << int(this->fontColor_[(i+3)%4]*255);
+        this->fontColorStr_ = stream.str();
+        GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueFontColor(\"" + this->getName() + "\", \"" + this->fontColorStr_ + "\")");
+    }
+
+    /**
+    @brief
+        Get the NotificationQueueCEGUI with the input name.
+    @param name
+        The name of the NotificationQueueCEGUI to be got.
+    @return
+        Returns a pointer to the NotificationQueueCEGUI, or NULL if it doesn't exist.
+    */
+    /*static*/ NotificationQueueCEGUI* NotificationQueueCEGUI::getQueue(const std::string& name)
+    {
+        NotificationQueue* queue = NotificationManager::getInstance().getQueue(name);
+        if(queue == NULL || !queue->isA(Class(NotificationQueueCEGUI)))
+            return NULL;
+        return static_cast<NotificationQueueCEGUI*>(queue);
+    }
+
+    /**
+    @brief
+        Is called by the NotificationQueue when a notification was pushed.
+    @param notification
+        The Notification that was pushed.
+    */
+    void NotificationQueueCEGUI::notificationPushed(Notification* notification)
+    {
+         // Push the Notification to the GUI.
+        if(GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
+    }
+
+    /**
+    @brief
+        Is called by the NotificationQueue when a notification was popped.
+    */
+    void NotificationQueueCEGUI::notificationPopped(void)
+    {
+        // Pops the Notification from the GUI.
+        if(GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".popNotification(\"" + this->getName() + "\")");
+    }
+
+    /**
+    @brief Is called when a notification was removed.
+    @param index The index the removed notification was at.
+    */
+    void NotificationQueueCEGUI::notificationRemoved(unsigned int index)
+    {
+        // Removes the Notification from the GUI.
+        if(GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
+    }
+
+    /**
+    @brief
+        Clears the NotificationQueue by removing all NotificationContainers.
+    @param noGraphics
+        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
+    */
+    void NotificationQueueCEGUI::clear(bool noGraphics)
+    {
+        NotificationQueue::clear(noGraphics);
+
+        // Clear the NotificationQueue in the GUI.
+        if(GameMode::showsGraphics() && !noGraphics)
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".clearQueue(\"" + this->getName() + "\")");
+    }
+
+    /**
+    @brief
+        Creates the NotificationQueue in lua.
+    */
+    void NotificationQueueCEGUI::create(void)
+    {
+        if(GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
+    }
+
+}
+

Copied: code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.h (from rev 8452, code/branches/tutoriallevel2/src/modules/notifications/NotificationQueueCEGUI.h)
===================================================================
--- code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.h	                        (rev 0)
+++ code/branches/tutoriallevel3/src/modules/notifications/NotificationQueueCEGUI.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -0,0 +1,155 @@
+/*
+ *   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 NotificationQueueCEGUI.h
+    @brief Definition of the NotificationQueueCEGUI class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationOueueCEGUI_H__
+#define _NotificationOueueCEGUI_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <string>
+#include "util/Math.h"
+
+#include "NotificationManager.h"
+
+#include "NotificationQueue.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        Displays @ref orxonox::Notification "Notifications" using CEGUI.
+
+        Apart form the parameters inherited by the @ref orxonox::NotificationQueue "NotificationQueue", there are some more parameters that influence the behavior of the NotificationQueueCEGUI:
+        - @b displaySize The size of the window that displays the NotificationQueue.
+        - @b position The position if the window that displays the NotificationQueue.
+        - @b alignment The horizontal alignment of the displayed Notifications.
+        - @b fontSize The font size of the displayed Notifications.
+        - @b fontColor The font color of the displayed Notifications.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @see NotificationQueue
+    @ingroup Notifications
+    */
+    class _NotificationsExport NotificationQueueCEGUI // tolua_export
+        : public NotificationQueue
+    { // tolua_export
+
+        public:
+            NotificationQueueCEGUI(const std::string& name, const std::string& senders = NotificationListener::ALL, unsigned int size = NotificationQueue::DEFAULT_SIZE, unsigned int displayTime = NotificationQueue::DEFAULT_DISPLAY_TIME);
+            virtual ~NotificationQueueCEGUI();
+
+            void destroy(bool noGraphics = false); // Destroys the NotificationQueue.
+
+            /**
+            @brief Set the size of the window that displays the NotificationQueue.
+            @param size A vector whose first component is the relative width of the window (a value between 0 and 1) and whose second component is the absolute width in pixels (additional to the relative width, can be negative). The height is set such that exactly as many Notifications fit as is the maximum size of the NotificationQueue (in terms of the number of Notifications).
+            */
+            inline void setDisplaySize(const Vector2& size)
+                { this->setDisplaySize(Vector4(size.x, size.y, 0.0, 0.0)); }
+            void setDisplaySize(const Vector4& size); // Set the size of the window that displays the NotificationQueue.
+            /**
+            @brief Get the size of the window that displays the NotificationQueue.
+            @return Returns a vector with the display size.
+            */
+            inline const Vector4& getDisplaySize(void) const
+                { return this->displaySize_; }
+
+            void setPosition(const Vector4& position); // Set the position of the window that displays the NotificationQueue.
+            /**
+            @brief Get the position of the window that displays the NotificationQueue.
+            @return Returns a vector with the position.
+            */
+            inline const Vector4& getPosition(void) const
+                { return this->position_; }
+
+            void setAlignment(const std::string& alignment); // Set the horizontal alignment of the Notifications text.
+            /**
+            @brief Get the horizontal alignment of the Notifications text.
+            @return Returns a string with the horizontal alignment property.
+            */
+            inline const std::string& getAlignment(void)
+                { return this->alignment_; }
+
+            void setFontSize(unsigned int size); // Set the font size of the text displayed by this NotificationQueue.
+            /**
+            @brief Get the font size of the text displayed by this NotificationQueue.
+            @return Returns the font size.
+            */
+            inline unsigned int getFontSize(void)
+                { return this->fontSize_; }
+
+            void setFontColor(const Vector4& color); // Set the font color if the text displayed by this NotificationQueue.
+            /**
+            @brief Get the font color of the text displayed by this NotificationQueue.
+            @return Returns a vector with the components being RGBA, with values from 0 to 1.
+            */
+            inline const Vector4& getFontColor(void) const
+                { return this->fontColor_; }
+            /**
+            @brief Get the font color of the text displayed by this NotificationQueue.
+            @return Returns a string with the ARGB values in hexadecimal format.
+            */
+            inline const std::string& getFontColorStr(void) const
+                { return this->fontColorStr_; }
+
+            static NotificationQueueCEGUI* getQueue(const std::string& name); // tolua_export // Get the NotificationQueueCEGUI with the input name.
+            
+        protected:
+            virtual void notificationPushed(Notification* notification); // Is called by the NotificationQueue when a notification was pushed
+            virtual void notificationPopped(void); // Is called by the NotificationQueue when a notification was popped.
+            virtual void notificationRemoved(unsigned int index); // Is called when a notification was removed.
+            
+            virtual void clear(bool noGraphics = false); // Clears the NotificationQueue by removing all NotificationContainers.
+
+        protected:
+            static const std::string NOTIFICATION_LAYER; //!< The name of the NotificationLayer menu sheet.
+            
+        private:
+            Vector4 displaySize_; //!< The size of the window that displays the NotificationQueue.
+            Vector4 position_; //!< The position of the window that displays the NotificationQueue.
+            std::string alignment_; //!< The horizontal alignment of the Notifications text.
+            unsigned int fontSize_; //!< The font size of the Notifications text.
+            Vector4 fontColor_; //!< The font color of the Notifications text as a vector, in RGBA form, with values from 0 to 1.
+            std::string fontColorStr_; //!< The font color of the Notifications text as a string with the ARGB hexadecimal values.
+            
+            void create(void); // Creates the NotificationQueue in lua.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _NotificationQueueCEGUI_H__ */

Modified: code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -279,7 +279,9 @@
     @brief
         Check whether the DistanceTrigger is triggered.
         It is triggered if it is triggered according only to its mode (i.e. its sub-triggers) and if a target is in range.
-    @param
+    @param mode
+        The mode for which it is tested, whether the DistanceTrigger is triggered.
+    @return
         Returns true if it is triggered ,false if not.
     */
     bool DistanceTrigger::isTriggered(TriggerMode::Value mode)

Modified: code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/objects/triggers/DistanceTrigger.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -70,7 +70,7 @@
         - @b distance Which specifies the maximum distance at which the DistanceTrigger still triggers, i.e. its range. Default is <code>100</code>.
         - @b target Which specifies the class of objects that can trigger the DistanceTrigger. Default is <code>"Pawn"</code>.
         - @b beaconMode Which specifies, whether the DistanceTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
-        - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+        - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
 
         A simple DistanceTrigger could look like this:
         @code

Modified: code/branches/tutoriallevel3/src/modules/objects/triggers/EventTrigger.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/objects/triggers/EventTrigger.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/objects/triggers/EventTrigger.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -59,7 +59,7 @@
         @endcode
 
     @see Trigger
-        For more information on @ref oroxnox::Trigger "Triggers".
+        For more information on @ref orxonox::Trigger "Triggers".
 
     @author
         Fabian 'x3n' Landau

Modified: code/branches/tutoriallevel3/src/modules/objects/triggers/MultiTrigger.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/objects/triggers/MultiTrigger.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/objects/triggers/MultiTrigger.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -197,7 +197,6 @@
                         // If the activity is different from what it is now, change it and fire an Event.
                         if(bActive ^ this->isActive(state->originator))
                         {
-
                             bool bFire = true;
 
                             // Add the originator to the objects activating this MultiTrigger.

Modified: code/branches/tutoriallevel3/src/modules/objects/triggers/TriggerBase.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/objects/triggers/TriggerBase.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/objects/triggers/TriggerBase.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -132,6 +132,12 @@
             */
             inline int getActivations(void) const
                 { return this->remainingActivations_; }
+            /**
+            @brief Check whether the trigger has still at least one remaining activation.
+            @return Returns true if the trigger has remaining activations (i.e. the number of remaining activations is not zero).
+            */
+            inline bool hasRemainingActivations(void) const
+                { return this->remainingActivations_ > 0 || this->remainingActivations_ == INF_s; }
 
             /**
             @brief Set the invert-mode of triggerhe trigger.

Modified: code/branches/tutoriallevel3/src/modules/overlays/hud/CMakeLists.txt
===================================================================
--- code/branches/tutoriallevel3/src/modules/overlays/hud/CMakeLists.txt	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/overlays/hud/CMakeLists.txt	2011-05-11 22:31:23 UTC (rev 8453)
@@ -6,7 +6,6 @@
   HUDHealthBar.cc
   HUDTimer.cc
   ChatOverlay.cc
-  GametypeStatus.cc
   AnnounceMessage.cc
   KillMessage.cc
   DeathMessage.cc

Deleted: code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,126 +0,0 @@
-/*
- *   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:
- *      Fabian 'x3n' Landau
- *   Co-authors:
- *      ...
- *
- */
-
-#include "GametypeStatus.h"
-
-#include "util/Convert.h"
-#include "core/CoreIncludes.h"
-#include "core/command/ConsoleCommand.h"
-#include "infos/GametypeInfo.h"
-#include "infos/PlayerInfo.h"
-#include "worldentities/ControllableEntity.h"
-#include "worldentities/pawns/Spectator.h"
-//#include "gametypes/Gametype.h"
-
-namespace orxonox
-{
-    CreateFactory(GametypeStatus);
-
-    static const std::string __CC_GametypeStatus_name = "GametypeStatus";
-    static const std::string __CC_displayCaption_name = "displayCaption";
-
-    SetConsoleCommand(__CC_GametypeStatus_name, __CC_displayCaption_name, &GametypeStatus::setDisplayCaption);
-
-    GametypeStatus::GametypeStatus(BaseObject* creator) : OverlayText(creator)
-    {
-        RegisterObject(GametypeStatus);
-
-        //this->game_ = 0;
-        this->owner_ = 0;
-        this->bNoCaption_ = false;
-        //this->bForcedSpawn_ = false;
-
-        ModifyConsoleCommand(__CC_GametypeStatus_name, __CC_displayCaption_name).setObject(this);
-    }
-
-    GametypeStatus::~GametypeStatus()
-    {
-        ModifyConsoleCommand(__CC_GametypeStatus_name, __CC_displayCaption_name).setObject(0);
-    }
-
-    void GametypeStatus::tick(float dt)
-    {
-        SUPER(GametypeStatus, tick, dt);
-
-        if (this->owner_ && this->owner_->getGametypeInfo() && this->owner_->getControllableEntity())
-        {
-            //if (this->game_)
-            //    this->bForcedSpawn_ = this->game_->getForceSpawn();
-            //else
-            //    this->bForcedSpawn_ = false;
-
-            const GametypeInfo* gtinfo = this->owner_->getGametypeInfo();
-            ControllableEntity* ce = this->owner_->getControllableEntity();
-
-            if (this->bNoCaption_) // No captions are displayed.
-            {
-                this->setCaption("");
-                return;
-            }
-
-            if (!gtinfo->hasStarted() && !gtinfo->isStartCountdownRunning())
-            {
-                if (!this->owner_->isReadyToSpawn())
-                    this->setCaption("Press [Fire] to start the match");
-                else
-                    this->setCaption("Waiting for other players");
-            }
-            else if (!gtinfo->hasEnded())
-            {
-                if (gtinfo->isStartCountdownRunning())
-                    this->setCaption(multi_cast<std::string>(static_cast<int>(ceil(gtinfo->getStartCountdown()))));
-                else if (ce->isA(Class(Spectator))/*&&(!bForcedSpawn_)*/)
-                    this->setCaption("Press [Fire] to respawn");
-                else
-                    this->setCaption("");
-            }
-            else
-                this->setCaption("Game has ended");
-        }
-    }
-
-
-    void GametypeStatus::changedOwner()
-    {
-        SUPER(GametypeStatus, changedOwner);
-        //this->game_ = orxonox_cast<Gametype*>(this->getOwner());
-        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
-    }
-
-    /**
-    @brief
-        Sets whether the gametype status is displayed.
-    @param bValue
-        If true captions are displayed, if false, not.
-    */
-    void GametypeStatus::setDisplayCaption(bool bValue)
-    {
-        this->bNoCaption_ = !bValue;
-    }
-
-}

Deleted: code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/overlays/hud/GametypeStatus.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,58 +0,0 @@
-/*
- *   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:
- *      Fabian 'x3n' Landau
- *   Co-authors:
- *      ...
- *
- */
-
-#ifndef _GametypeStatus_H__
-#define _GametypeStatus_H__
-
-#include "overlays/OverlaysPrereqs.h"
-
-#include "tools/interfaces/Tickable.h"
-#include "overlays/OverlayText.h"
-
-namespace orxonox
-{
-    class _OverlaysExport GametypeStatus : public OverlayText, public Tickable
-    {
-        public:
-            GametypeStatus(BaseObject* creator);
-            virtual ~GametypeStatus();
-
-            virtual void tick(float dt);
-            virtual void changedOwner();
-
-            void setDisplayCaption(bool bValue); //!< Toggles whether the gametype status is displayed.
-
-        private:
-            //Gametype* game_;
-            PlayerInfo* owner_;
-            bool bNoCaption_;
-            //bool bForcedSpawn_;
-
-    };
-}
-#endif /* _GametypeStatus_H__ */

Modified: code/branches/tutoriallevel3/src/modules/questsystem/QuestDescription.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/questsystem/QuestDescription.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/questsystem/QuestDescription.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -39,7 +39,7 @@
 
 #include "infos/PlayerInfo.h"
 
-#include "notifications/NotificationManager.h"
+#include "interfaces/NotificationListener.h"
 
 namespace orxonox
 {
@@ -118,7 +118,7 @@
             return false;
         }
 
-        NotificationManager::sendNotification(message, player->getClientID(), QuestDescription::SENDER);
+        NotificationListener::sendNotification(message, QuestDescription::SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
         return true;
     }
 

Modified: code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.cc
===================================================================
--- code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -273,6 +273,9 @@
     */
     int QuestManager::getNumSubQuests(Quest* quest, PlayerInfo* player)
     {
+        if(quest == NULL)
+            return this->getNumRootQuests(player);
+
         std::list<Quest*> quests = quest->getSubQuestList();
         int numQuests = 0;
         for(std::list<Quest*>::iterator it = quests.begin(); it != quests.end(); it++)
@@ -295,6 +298,9 @@
     */
     Quest* QuestManager::getSubQuest(Quest* quest, PlayerInfo* player, int index)
     {
+        if(quest == NULL)
+            return this->getRootQuest(player, index);
+
         std::list<Quest*> quests = quest->getSubQuestList();
         for(std::list<Quest*>::iterator it = quests.begin(); it != quests.end(); it++)
         {
@@ -311,7 +317,8 @@
         The quest to get the hints of.
     @param player
         The player.
-    @return Returns the number of QuestHints of the input Quest for the input player.
+    @return
+        Returns the number of QuestHints of the input Quest for the input player.
     */
     int QuestManager::getNumHints(Quest* quest, PlayerInfo* player)
     {
@@ -334,6 +341,8 @@
         The player.
     @param index
         The index of the QuestHint.
+    @return
+        Returns a pointer to the index-th QuestHint of the input Quest for the input player.
     */
     QuestHint* QuestManager::getHints(Quest* quest, PlayerInfo* player, int index)
     {
@@ -348,6 +357,19 @@
 
     /**
     @brief
+        Get the parent-quest of the input Quest.
+    @param quest
+        The Quest to get the parent-quest of.
+    @return
+        Returns a pointer to the parent-quest of the input Quest.
+    */
+    Quest* QuestManager::getParentQuest(Quest* quest)
+    {
+        return quest->getParentQuest();
+    }
+
+    /**
+    @brief
         Get the QuestDescription of the input Quest.
     @param item
         The Quest to get the QuestDescription of.
@@ -374,6 +396,32 @@
 
     /**
     @brief
+        Get the id of the input Quest.
+    @param item
+        The Quest to get the id of.
+    @return
+        Returns the id of the input Quest.
+    */
+    const std::string QuestManager::getId(Quest* item) const
+    {
+        return item->getId();
+    }
+
+    /**
+    @brief
+        Get the id of the input QuestHint.
+    @param item
+        The QuestHint to get the id of.
+    @return
+        Returns the id of the input QuestHint.
+    */
+    const std::string QuestManager::getId(QuestHint* item) const
+    {
+        return item->getId();
+    }
+
+    /**
+    @brief
         Retrieve the player for a certain GUI.
     @param guiName
         The name of the GUI the player is retrieved for.

Modified: code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.h
===================================================================
--- code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/modules/questsystem/QuestManager.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -80,8 +80,13 @@
             int getNumHints(Quest* quest, orxonox::PlayerInfo* player); //!< Get the number of QuestHints of the input Quest for the input player.
             QuestHint* getHints(Quest* quest, orxonox::PlayerInfo* player, int index); //!< Get the index-th QuestHint of the input Quest for the input player.
 
-            QuestDescription* getDescription(Quest* item);
-            QuestDescription* getDescription(QuestHint* item);
+            Quest* getParentQuest(Quest* quest); //!< Get the parent-quest of the input Quest.
+
+            QuestDescription* getDescription(Quest* item); //!< Get the QuestDescription of the input Quest.
+            QuestDescription* getDescription(QuestHint* item); //!< Get the QuestDescription of the input QuestHint.
+
+            const std::string getId(Quest* item) const; //!< Get the id of the input Quest.
+            const std::string getId(QuestHint* item) const; //!< Get the id of the input QuestHint.
             // tolua_end
 
             bool registerQuest(Quest* quest); //!< Registers a Quest in the QuestManager.

Modified: code/branches/tutoriallevel3/src/orxonox/LevelManager.cc
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/LevelManager.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/LevelManager.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -221,6 +221,7 @@
                 this->nextIndex_ = 0;
                 this->nextLevel_ = this->availableLevels_.begin();
             }
+
             while(this->nextIndex_ != index)
             {
                 this->nextIndex_++;

Modified: code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.cc
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -58,6 +58,8 @@
 
         this->defaultControllableEntity_ = Class(Spectator);
 
+        this->bFirstTick_ = true;
+        
         this->bAutoStart_ = false;
         this->bForceSpawn_ = false;
         this->numberOfBots_ = 0;
@@ -111,6 +113,13 @@
     {
         SUPER(Gametype, tick, dt);
 
+        // Activate the GametypeInfo.
+        if(this->bFirstTick_)
+        {
+            this->gtinfo_->setActive(true);
+            this->bFirstTick_ = false;
+        }
+
         //count timer
         if (timerIsActive_)
         {
@@ -120,12 +129,12 @@
                 this->time_ -= dt;
         }
 
-        if (this->gtinfo_->bStartCountdownRunning_ && !this->gtinfo_->bStarted_)
-            this->gtinfo_->startCountdown_ -= dt;
+        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
+            this->gtinfo_->countdownStartCountdown(dt);
 
-        if (!this->gtinfo_->bStarted_)
+        if (!this->gtinfo_->hasStarted())
             this->checkStart();
-        else if (!this->gtinfo_->bEnded_)
+        else if (!this->gtinfo_->hasEnded())
             this->spawnDeadPlayersIfRequested();
 
         this->assignDefaultPawnsIfNeeded();
@@ -135,14 +144,14 @@
     {
         this->addBots(this->numberOfBots_);
 
-        this->gtinfo_->bStarted_ = true;
+        this->gtinfo_->start();
 
         this->spawnPlayersIfRequested();
     }
 
     void Gametype::end()
     {
-        this->gtinfo_->bEnded_ = true;
+        this->gtinfo_->end();
 
         for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
         {
@@ -269,6 +278,9 @@
                     }
                 }
 
+                if(victim->getPlayer()->isHumanPlayer())
+                    this->gtinfo_->pawnKilled(victim->getPlayer());
+
                 ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getCreator());
                 if (victim->getCamera())
                 {
@@ -345,7 +357,7 @@
             {
                 it->second.state_ = PlayerState::Dead;
 
-                if (!it->first->isReadyToSpawn() || !this->gtinfo_->bStarted_)
+                if (!it->first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
                 {
                     this->spawnPlayerAsDefaultPawn(it->first);
                     it->second.state_ = PlayerState::Dead;
@@ -356,14 +368,14 @@
 
     void Gametype::checkStart()
     {
-        if (!this->gtinfo_->bStarted_)
+        if (!this->gtinfo_->hasStarted())
         {
-            if (this->gtinfo_->bStartCountdownRunning_)
+            if (this->gtinfo_->isStartCountdownRunning())
             {
-                if (this->gtinfo_->startCountdown_ <= 0)
+                if (this->gtinfo_->getStartCountdown() <= 0.0f)
                 {
-                    this->gtinfo_->bStartCountdownRunning_ = false;
-                    this->gtinfo_->startCountdown_ = 0;
+                    this->gtinfo_->stopStartCountdown();
+                    this->gtinfo_->setStartCountdown(0.0f);;
                     this->start();
                 }
             }
@@ -383,15 +395,20 @@
                             allplayersready = false;
                         if (it->first->isHumanPlayer())
                             hashumanplayers = true;
+
+                        // Inform the GametypeInfo that the player is ready to spawn.
+                        // TODO: Can it happen, that that changes?
+                        if(it->first->isHumanPlayer() && it->first->isReadyToSpawn())
+                            this->gtinfo_->playerReadyToSpawn(it->first);
                     }
                     if (allplayersready && hashumanplayers)
                     {
                         // If in developer's mode, there is no start countdown.
                         if(Core::getInstance().inDevMode())
-                            this->gtinfo_->startCountdown_ = 0;
+                            this->start();
                         else
-                            this->gtinfo_->startCountdown_ = this->initialStartCountdown_;
-                        this->gtinfo_->bStartCountdownRunning_ = true;
+                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
+                        this->gtinfo_->startStartCountdown();
                     }
                 }
             }
@@ -401,8 +418,10 @@
     void Gametype::spawnPlayersIfRequested()
     {
         for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
+        {
             if (it->first->isReadyToSpawn() || this->bForceSpawn_)
                 this->spawnPlayer(it->first);
+        }
     }
 
     void Gametype::spawnDeadPlayersIfRequested()
@@ -421,6 +440,10 @@
             this->playerPreSpawn(player);
             player->startControl(spawnpoint->spawn());
             this->players_[player].state_ = PlayerState::Alive;
+
+            if(player->isHumanPlayer())
+                this->gtinfo_->playerSpawned(player);
+            
             this->playerPostSpawn(player);
         }
         else

Modified: code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.h
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -77,9 +77,9 @@
                 { return this->gtinfo_; }
 
             inline bool hasStarted() const
-                { return this->gtinfo_->bStarted_; }
+                { return this->gtinfo_->hasStarted(); }
             inline bool hasEnded() const
-                { return this->gtinfo_->bEnded_; }
+                { return this->gtinfo_->hasEnded(); }
 
             virtual void start();
             virtual void end();
@@ -113,14 +113,14 @@
                 { this->spawnpoints_.insert(spawnpoint); }
 
             inline bool isStartCountdownRunning() const
-                { return this->gtinfo_->bStartCountdownRunning_; }
+                { return this->gtinfo_->isStartCountdownRunning(); }
             inline float getStartCountdown() const
-                { return this->gtinfo_->startCountdown_; }
+                { return this->gtinfo_->getStartCountdown(); }
 
             inline void setHUDTemplate(const std::string& name)
-                { this->gtinfo_->hudtemplate_ = name; }
+                { this->gtinfo_->setHUDTemplate(name); }
             inline const std::string& getHUDTemplate() const
-                { return this->gtinfo_->hudtemplate_; }
+                { return this->gtinfo_->getHUDTemplate(); }
 
             void addBots(unsigned int amount);
             void killBots(unsigned int amount = 0);
@@ -167,6 +167,8 @@
 
             SmartPtr<GametypeInfo> gtinfo_;
 
+            bool bFirstTick_; //!< Whether this is the first tick or not.
+            
             bool bAutoStart_;
             bool bForceSpawn_;
 

Modified: code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.cc
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -22,18 +22,28 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
 
+/**
+    @file GametypeInfo.cc
+    @brief Implementation of the GametypeInfo class
+*/
+
 #include "GametypeInfo.h"
 
 #include "core/CoreIncludes.h"
 #include "core/GameMode.h"
+#include "network/Host.h"
 #include "network/NetworkFunction.h"
-#include "network/Host.h"
+#include "util/Convert.h"
+
 #include "interfaces/GametypeMessageListener.h"
+#include "interfaces/NotificationListener.h"
 
+#include "PlayerInfo.h"
+
 namespace orxonox
 {
     CreateUnloadableFactory(GametypeInfo);
@@ -44,14 +54,23 @@
     registerMemberNetworkFunction(GametypeInfo, dispatchStaticMessage);
     registerMemberNetworkFunction(GametypeInfo, dispatchFadingMessage);
 
+    /*static*/ const std::string GametypeInfo::NOTIFICATION_SENDER("gameinfo");
+
+    /**
+    @brief
+        Registers and initializes the object.
+    */
     GametypeInfo::GametypeInfo(BaseObject* creator) : Info(creator)
     {
         RegisterObject(GametypeInfo);
 
+        this->bActive_ = false; // At first the GametypeInfo is inactive.
+        
         this->bStarted_ = false;
         this->bEnded_ = false;
-        this->startCountdown_ = 0;
+        this->startCountdown_ = 0.0f;
         this->bStartCountdownRunning_ = false;
+        this->counter_ = 0;
 
         this->registerVariables();
     }
@@ -62,13 +81,226 @@
 
     void GametypeInfo::registerVariables()
     {
-        registerVariable(this->bStarted_,               VariableDirection::ToClient);
-        registerVariable(this->bEnded_,                 VariableDirection::ToClient);
+        registerVariable(this->bStarted_,               VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStarted));
+        registerVariable(this->bEnded_,                 VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedEnded));
+        registerVariable(this->bStartCountdownRunning_, VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStartCountdownRunning));
         registerVariable(this->startCountdown_,         VariableDirection::ToClient);
-        registerVariable(this->bStartCountdownRunning_, VariableDirection::ToClient);
+        registerVariable(this->counter_,                VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedCountdownCounter));
         registerVariable(this->hudtemplate_,            VariableDirection::ToClient);
     }
 
+    /**
+    @brief
+        Is called when the activity has changed.
+    */
+    void GametypeInfo::changedActivity(void)
+    {
+        SUPER(GametypeInfo, changedActivity);
+
+        // If the GametypeInfo has become active the "Press [Fire] to start the match" notification is sent.
+        if(this->isActive())
+            NotificationListener::sendNotification("Press [Fire] to start the match", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the game has changed to started.
+    */
+    void GametypeInfo::changedStarted(void)
+    {
+        
+    }
+
+    /**
+    @brief
+        Is called when the game has changed to ended.
+    */
+    void GametypeInfo::changedEnded(void)
+    {
+        // If the game has ended, a "Game has ended" notification is displayed.
+        if(this->hasEnded())
+            NotificationListener::sendNotification("Game has ended", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown has been either started or stopped.
+    */
+    void GametypeInfo::changedStartCountdownRunning(void)
+    {
+        // Clear the notifications if the countdown has stopped running.
+        if(!this->hasStarted() && !this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER);
+        // Send first countdown notification if the countdown has started.
+        if(!this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown counter has changed.
+    */
+    void GametypeInfo::changedCountdownCounter(void)
+    {
+        // Send countdown notification if the counter has gone down.
+        if(!this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when a player has become ready to spawn.
+    @param player
+        The player that has become ready to spawn.
+    */
+    void GametypeInfo::changedReadyToSpawn(PlayerInfo* player)
+    {
+        // Send "Waiting for other players" over the network to the right player if a player has become ready to spawn.
+        if(!this->hasStarted() && !this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification("Waiting for other players", GametypeInfo::NOTIFICATION_SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
+        // Clear the notifications if the player has respawned.
+        if(this->hasStarted() && !this->hasEnded())
+            NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER, notificationSendMode::network, player->getClientID());
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has started.
+    */
+    void GametypeInfo::start(void)
+    {
+        if(this->bStarted_)
+            return;
+        
+        this->bStarted_ = true;
+        this->changedStarted();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has ended.
+    */
+    void GametypeInfo::end(void)
+    {
+        if(this->bEnded_)
+            return;
+
+        this->bEnded_ = true;
+        this->changedEnded();
+    }
+
+    /**
+    @brief
+        Set the start countdown to the input value.
+    @param countdown
+        The countdown to be set.
+    */
+    void GametypeInfo::setStartCountdown(float countdown)
+    {
+        if(this->startCountdown_ == countdown || countdown < 0.0f)
+            return;
+        
+        this->startCountdown_ = countdown;
+        // Set the counter to the ceiling of the current countdown.
+        this->counter_ = ceil(countdown);
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Count down the start countdown by the specified value.
+    @param countDown
+        The amount by which we count down.
+    */
+    void GametypeInfo::countdownStartCountdown(float countDown)
+    {
+        float newCountdown = this->startCountdown_ - countDown;
+        // If we have switched integers or arrived at zero, we also count down the start countdown counter.
+        if(ceil(newCountdown) != ceil(this->startCountdown_) || newCountdown <= 0.0f)
+            this->countDown();
+        this->startCountdown_ = newCountdown;
+    }
+
+    /**
+    @brief
+        Count down the start countdown counter.
+    */
+    void GametypeInfo::countDown()
+    {
+        if(this->counter_ == 0)
+            return;
+        
+        this->counter_--;
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the start of the start countdown.
+    */
+    void GametypeInfo::startStartCountdown(void)
+    {
+        if(this->bStartCountdownRunning_)
+            return;
+        
+        this->bStartCountdownRunning_ = true;
+        this->changedStartCountdownRunning();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the stop of the start countdown.
+    */
+    void GametypeInfo::stopStartCountdown(void)
+    {
+        if(!this->bStartCountdownRunning_)
+            return;
+        
+        this->bStartCountdownRunning_ = false;
+        this->changedStartCountdownRunning();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that is ready to spawn.
+    @param player
+        The player that is ready to spawn.
+    */
+    void GametypeInfo::playerReadyToSpawn(PlayerInfo* player)
+    {
+        // If the player has spawned already.
+        if(this->spawned_.find(player) != this->spawned_.end())
+            return;
+
+        this->spawned_.insert(player);
+        this->changedReadyToSpawn(player);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player whose Pawn has been killed.
+    @param player
+        The player whose Pawn has been killed.
+    */
+    void GametypeInfo::pawnKilled(PlayerInfo* player)
+    {
+        NotificationListener::sendNotification("Press [Fire] to respawn", GametypeInfo::NOTIFICATION_SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
+        // Remove the player from the list of players that have spawned, since it currently is not.
+        this->spawned_.erase(player);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that has spawned.
+    @param player
+        The player that has spawned.
+    */
+    void GametypeInfo::playerSpawned(PlayerInfo* player)
+    {
+        if(this->hasStarted() && !this->hasEnded())
+            NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER, notificationSendMode::network, player->getClientID());
+    }
+
     void GametypeInfo::sendAnnounceMessage(const std::string& message)
     {
         if (GameMode::isMaster())

Modified: code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.h
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/infos/GametypeInfo.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -22,20 +22,36 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
 
+/**
+    @file GametypeInfo.h
+    @brief Definition of the GametypeInfo class
+*/
+
 #ifndef _GametypeInfo_H__
 #define _GametypeInfo_H__
 
 #include "OrxonoxPrereqs.h"
 
 #include <string>
+
 #include "Info.h"
 
 namespace orxonox
 {
+
+    /**
+    @brief
+        The GametypeInfo class keeps track of the state of the game and provides facilities to inform the player about it.
+
+    @author
+        Fabian 'x3n' Landau
+    @author
+        Damian 'Mozork' Frick
+    */
     class _OrxonoxExport GametypeInfo : public Info
     {
         friend class Gametype;
@@ -44,16 +60,48 @@
             GametypeInfo(BaseObject* creator);
             virtual ~GametypeInfo();
 
+            virtual void changedActivity(void); // Is called when the activity has changed.
+
+            /**
+            @brief Get whether the game has started yet.
+            @return Returns true if the game has started, false if not.
+            */
             inline bool hasStarted() const
                 { return this->bStarted_; }
+            void changedStarted(void); // Is called when the game has changed to started.
+            
+            /**
+            @brief Get whether the game has ended yet.
+            @return Returns true if the game has ended, false if not.
+            */
             inline bool hasEnded() const
                 { return this->bEnded_; }
+            void changedEnded(void); // Is called when the game has changed to ended.
 
+            /**
+            @brief Get whether the start countdown is currently running.
+            @return Returns true if the countdown is running, false if not.
+            */
             inline bool isStartCountdownRunning() const
                 { return this->bStartCountdownRunning_; }
+            void changedStartCountdownRunning(void); // Is called when the start countdown has been either started or stopped.
+
+            /**
+            @brief Get the current value of the start countdown.
+            @return Returns the current value of the start countdown.
+            */
             inline float getStartCountdown() const
                 { return this->startCountdown_; }
 
+            /**
+            @brief Get the current start countdown counter.
+                   The start countdown counter only has integer values that correspond to the actually displayed countdown.
+            @return Returns the current integer countdown counter.
+            */
+            inline unsigned int getStartCountdownCounter() const
+                { return this->counter_; }
+            void changedCountdownCounter(void); // Is called when the start countdown counter has changed.
+
             inline const std::string& getHUDTemplate() const
                 { return this->hudtemplate_; }
 
@@ -69,15 +117,37 @@
             void dispatchDeathMessage(const std::string& message);
             void dispatchStaticMessage(const std::string& message,const ColourValue& colour);
             void dispatchFadingMessage(const std::string& message);
+            
+        protected:
+            void changedReadyToSpawn(PlayerInfo* player); // Is called when a player has become ready to spawn.
+            
+            void start(void); // Inform the GametypeInfo that the game has started.
+            void end(void); // Inform the GametypeInfo that the game has ended.
+            void setStartCountdown(float countdown); // Set the start countdown to the input value.
+            void countdownStartCountdown(float countDown); // Count down the start countdown by the specified value.
+            void countDown(); // Count down the start countdown counter.
+            void startStartCountdown(void); // Inform the GametypeInfo about the start of the start countdown.
+            void stopStartCountdown(void); // Inform the GametypeInfo about the stop of the start countdown.
+            void playerReadyToSpawn(PlayerInfo* player); // Inform the GametypeInfo about a player that is ready to spawn.
+            void pawnKilled(PlayerInfo* player); // Inform the GametypeInfo about a player whose Pawn has been killed.
+            void playerSpawned(PlayerInfo* player); // Inform the GametypeInfo about a player that has spawned.
 
+            inline void setHUDTemplate(const std::string& templateName)
+                { this->hudtemplate_ = templateName; };
+
         private:
             void registerVariables();
 
-            bool bStarted_;
-            bool bEnded_;
-            bool bStartCountdownRunning_;
-            float startCountdown_;
+            static const std::string NOTIFICATION_SENDER; //!< The name of the sender for the sending of notifications.
+
+            bool bStarted_; //!< Whether the game has started,
+            bool bEnded_; //!< Whether the game has ended.
+            bool bStartCountdownRunning_; //!< Whether the start countdown is running.
+            float startCountdown_; //!< The current value of the start countdown.
+            unsigned int counter_; //!< The current integer value of the start countdown, the start countdown counter.
             std::string hudtemplate_;
+            
+            std::set<PlayerInfo*> spawned_; //!< A set of players that are currently spawned.
     };
 }
 

Modified: code/branches/tutoriallevel3/src/orxonox/interfaces/CMakeLists.txt
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/interfaces/CMakeLists.txt	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/interfaces/CMakeLists.txt	2011-05-11 22:31:23 UTC (rev 8453)
@@ -1,5 +1,6 @@
 ADD_SOURCE_FILES(ORXONOX_SRC_FILES
   InterfaceCompilation.cc
+  NotificationListener.cc
   Pickupable.cc
   PickupCarrier.cc
   PickupListener.cc

Modified: code/branches/tutoriallevel3/src/orxonox/interfaces/InterfaceCompilation.cc
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/interfaces/InterfaceCompilation.cc	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/interfaces/InterfaceCompilation.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -85,12 +85,4 @@
     {
         RegisterRootObject(Rewardable);
     }
-
-    //----------------------------
-    // NotificationListener
-    //----------------------------
-    NotificationListener::NotificationListener()
-    {
-        RegisterRootObject(NotificationListener);
-    }
 }

Copied: code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.cc (from rev 8452, code/branches/tutoriallevel2/src/orxonox/interfaces/NotificationListener.cc)
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.cc	                        (rev 0)
+++ code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.cc	2011-05-11 22:31:23 UTC (rev 8453)
@@ -0,0 +1,161 @@
+/*
+ *   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 NotificationListener.cc
+    @brief Implementation of the NotificationListener class.
+*/
+
+#include "core/CoreIncludes.h"
+#include "network/Host.h"
+#include "network/NetworkFunction.h"
+#include "util/SubString.h"
+
+#include "interfaces/NotificationListener.h"
+
+namespace orxonox
+{
+    
+    /*static*/ const std::string NotificationListener::ALL("all");
+    /*static*/ const std::string NotificationListener::NONE("none");
+    
+    // Commands
+    /*static*/ const std::string NotificationListener::COMMAND_CLEAR("clear");
+    /*static*/ const std::string NotificationListener::COMMAND_NONE("none");
+    
+    registerStaticNetworkFunction(NotificationListener::sendHelper);
+    
+    NotificationListener::NotificationListener()
+    {
+        RegisterRootObject(NotificationListener);
+    }
+
+    /**
+    @brief
+        Helper method to send both notifications and commands over the network.
+    @param message
+        The message/command that should be sent.
+    @param sender
+        The sender that sent the notification/command.
+    @param sendMode
+        The mode in which the notification/command is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts.
+    @param clientId
+        The id of the client the notification/command should be sent to.
+    @param isCommand
+        Whether the message is a notification or a command.
+    @param messageType
+        The type of the notification, can be either 'info' or 'important'.
+    */
+    /*static*/ void NotificationListener::sendNetworkHelper(const std::string& message, const std::string& sender, notificationSendMode::Value sendMode, unsigned int clientId, bool isCommand, notificationMessageType::Value messageType)
+    {
+        // If we're in standalone mode or we're already no the right client we create and send the notification/command.
+        if(GameMode::isStandalone() || sendMode == notificationSendMode::local || (sendMode ==  notificationSendMode::network && Host::getPlayerID() == clientId))
+        {
+            sendHelper(message, sender, isCommand, messageType);
+        }
+        // If we're on the server (and the server is not the intended recipient of the notification/command) we send it over the network.
+        else if(GameMode::isServer() && sendMode == notificationSendMode::network && Host::getPlayerID() != clientId)
+        {
+            callStaticNetworkFunction(NotificationListener::sendHelper, clientId, message, sender, (unsigned int)messageType);
+        }
+        else if(GameMode::isServer() && sendMode == notificationSendMode::broadcast)
+        {
+            // TODO: Works as intended?
+            callStaticNetworkFunction(NotificationListener::sendHelper, NETWORK_PEER_ID_BROADCAST, message, sender, (unsigned int)messageType);
+        }
+    }
+
+    /**
+    @brief
+        Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+    @param message
+        The notification/command to be sent/executed.
+    @param sender
+        The sender that sent the notification/command.
+    @param isCommand
+        Whether the message is a command or a notification.
+    @param messageType
+        The type of the notification.
+    */
+    /*static*/ void NotificationListener::sendHelper(const std::string& message, const std::string& sender, bool isCommand, unsigned int messageType)
+    {
+        // Iterate through all NotificationListeners and notify them by calling the method they overloaded.
+        for(ObjectList<NotificationListener>::iterator it = ObjectList<NotificationListener>::begin(); it != ObjectList<NotificationListener>::end(); ++it)
+        {
+            // If the notification is a message.
+            if(!isCommand)
+                it->registerNotification(message, sender, notificationMessageType::Value(messageType));
+
+            // If the notification is a command.
+            if(isCommand)
+            {
+                notificationCommand::Value command = str2Command(message);
+                if(command != notificationCommand::none)
+                    it->executeCommand(command, sender);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Converts a string into the enum for a command.
+    @param string
+        The string to be converted.
+    @return
+        Returns the corresponding enum, notificationCommand::none if the command doesn't exist.
+    */
+    /*static*/ notificationCommand::Value NotificationListener::str2Command(const std::string& string)
+    {
+        notificationCommand::Value command = notificationCommand::none;
+
+        if(string == NotificationListener::COMMAND_CLEAR)
+            command = notificationCommand::clear;
+
+        return command;
+    }
+
+    /**
+    @brief
+        Helper method. Converts a command enum into its corresponding string.
+    @param command
+        The command to be converted.
+    @return
+        Returns the corresponding string.
+    */
+    /*static*/ const std::string& NotificationListener::command2Str(notificationCommand::Value command)
+    {
+        switch(command)
+        {
+            case notificationCommand::clear:
+                return NotificationListener::COMMAND_CLEAR;
+            default:
+                return NotificationListener::COMMAND_NONE;
+        }
+    }
+    
+}
\ No newline at end of file

Modified: code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.h
===================================================================
--- code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.h	2011-05-11 22:17:26 UTC (rev 8452)
+++ code/branches/tutoriallevel3/src/orxonox/interfaces/NotificationListener.h	2011-05-11 22:31:23 UTC (rev 8453)
@@ -20,7 +20,7 @@
  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *   Author:
- *      Fabian 'x3n' Landau
+ *      Damian 'Mozork' Frick
  *   Co-authors:
  *      ...
  *
@@ -47,19 +47,47 @@
 
 namespace orxonox
 {
-    class Notification;
+    // TODO: Document.
+    namespace notificationMessageType
+    {
+        enum Value {
+            info,
+            important
+        };
+    }
+    
+    namespace notificationSendMode
+    {
+        enum Value {
+            local,
+            network,
+            broadcast
+        };
+    }
+    
+    namespace notificationCommand
+    {
+        enum Value {
+            none,
+            clear
+        };
+    }
 
+    // TODO: Update doc.
     /**
     @brief
         NotificationListener interface.
 
-        The NotificationListener interface presents a means to being informed when @ref orxonox::Notification "Notifications" in the target set of this NotificationListener change. (e.g. @ref orxonox::Notification "Notifications" were added or removed)
-        When inheriting from a NotificationListener it is important to register (in the constructor) and unregister (in the destructor) it to and from the @ref orxonox::NotificationManager "NotificationManager".
+        The NotificationListener interface (or more precisely abstract class) presents a means of being informed when a new @ref orxonox::Notification "Notification" is sent.
+        The NotificationListener can be used to send a new notification message (with NotificationListener::sendNotification() ) or a new notification command (with NotificationListener::sendCommand() ). Each NotificationListener is then informed about the new @ref orxonox::Notification "Notification" and can take appropriate action. Currently the only NotificationListener ist the @ref orxonox::NotificationManager "NotificationManager" singleton.
 
+        When inheriting from a NotificationListener it is important to provide an appropriate implementation of registerNotification() and executeCommand().
+
     @author
-        Fabian 'x3n' Landau
-
+        Damian 'Mozork' Frick
+        
     @ingroup Notifications
+    @todo Consistent terminology between message, notification and command.
     */
     class _OrxonoxExport NotificationListener : virtual public OrxonoxClass
     {
@@ -68,22 +96,62 @@
             virtual ~NotificationListener() {}
 
             /**
-            @brief Get the senders that are targets of this NotificationListener.
-            @return Returns the set of senders that are targets of this NotificationListener.
+            @brief Sends a Notification with the specified message to the specified client from the specified sender.
+            @param message The message that should be sent.
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param messageType The type of the message, can be either 'info' or 'important'. Default is 'info'.
+            @param sendMode The mode in which the notification is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts. Default is notificationSendMode::local.
+            @param clientId The id of the client the notification should be sent to. Default is 0.
             */
-            virtual const std::set<std::string> & getTargetsSet(void) = 0;
+            static void sendNotification(const std::string& message, const std::string& sender = NotificationListener::NONE, notificationMessageType::Value messageType = notificationMessageType::info, notificationSendMode::Value sendMode = notificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(message, sender, sendMode, clientId, false, messageType); }
+            /**
+            @brief Sends a specified command to the specified client from the specified sender.
+            @param command The command that should be sent (and later executed).
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param sendMode The mode in which the command is sent, can be 'local' to send the command to the client where this function is executed, 'network' if the command is to be sent to the client with the specified clientID, or 'broadcast' if the command should be sent to all hosts. Default is notificationSendMode::local.
+            @param clientId The id of the client the command should be sent to. Default is 0.
+            */
+            static void sendCommand(const std::string& command, const std::string& sender = NotificationListener::NONE, notificationSendMode::Value sendMode = notificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(command, sender, sendMode, clientId, true); }
 
+            static void sendHelper(const std::string& message, const std::string& sender, bool isCommand = false, unsigned int messageMode = 0); // Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+
+            //TODO: Make protected?
+            
             /**
-            @brief Updates the whole NotificationListener.
-                   This is called by the @ref orxonox::NotificationManager "NotificationManager" when the @ref orxonox::Notification "Notifications" have changed so much, that the NotificationListener may have to re-initialize his operations.
+            @brief Registers a notification with the NotificationListener.
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param message The notification's message.
+            @param sender The sender of the notification.
+            @param type The type of the notification.
+            @return Returns true if the notification was successfully registered, false if not.
             */
-            virtual void update(void) = 0;
+            virtual bool registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
+                { return false; }
             /**
-            @brief Updates the NotificationListener, when a new Notification has come in at the specified time.
-            @param notification A pointer to the @ref orxonox::Notification "Notification".
-            @param time The time the @ref orxonox::Notification "Notification" has come in.
+            @brief Executes a command with the NotificationListener
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param command The command to be executed.
+            @param sender The sender of the command.
+            @return Returns true if the command was successfully executed, false if not.
             */
-            virtual void update(Notification* notification, const std::time_t & time) = 0;
+            virtual bool executeCommand(notificationCommand::Value command, const std::string& sender) { return false; }
+
+        public:
+            
+            static const std::string ALL; //!< Static string to indicate a sender that sends to all NotificationQueues.
+            static const std::string NONE; //!< Static string to indicate a sender that sends to no specific NotificationQueues.
+            
+            //! Commands
+            static const std::string COMMAND_CLEAR;
+            static const std::string COMMAND_NONE;
+            
+        protected:
+            static void sendNetworkHelper(const std::string& message, const std::string& sender, notificationSendMode::Value sendMode, unsigned int clientId, bool isCommand = false, notificationMessageType::Value messageType = notificationMessageType::info); // Helper method to send both notifications and commands over the network.
+
+            static notificationCommand::Value str2Command(const std::string& string); // Helper method. Converts a string into the enum for a command.
+            static const std::string& command2Str(notificationCommand::Value command); // Helper method. Converts a command enum into its corresponding string.
     };
 }
 




More information about the Orxonox-commit mailing list