Index: /code/branches/tutorial/data/defaultConfig/keybindings.ini
===================================================================
--- /code/branches/tutorial/data/defaultConfig/keybindings.ini	(revision 8050)
+++ /code/branches/tutorial/data/defaultConfig/keybindings.ini	(revision 8051)
@@ -19,5 +19,5 @@
 KeyDelete="scale 1 rotateRoll"
 KeyDivide=
-KeyDown="scale -1 moveFrontBack"
+KeyDown="scale -1 moveFrontBack | navigateGUI down"
 KeyE="scale -1 rotateRoll"
 KeyEnd=boost
@@ -42,5 +42,5 @@
 KeyF9=
 KeyG=greet
-KeyGrave="openConsole"
+KeyGrave="InGameConsole openConsole"
 KeyH=
 KeyHome=
@@ -52,5 +52,5 @@
 KeyKanji=
 KeyL=
-KeyLeft="scale -1 moveRightLeft"
+KeyLeft="scale -1 moveRightLeft | navigateGUI left"
 KeyLeftAlt=
 KeyLeftBracket=
@@ -93,5 +93,5 @@
 KeyNumpadAdd=
 KeyNumpadComma=
-KeyNumpadEnter=
+KeyNumpadEnter="navigateGUI enter"
 KeyNumpadEquals=
 KeyNumpadPeriod=
@@ -108,6 +108,6 @@
 KeyQ="scale 1 rotateRoll"
 KeyR="scale 1 moveUpDown"
-KeyReturn=
-KeyRight="scale 1 moveRightLeft"
+KeyReturn="navigateGUI enter"
+KeyRight="scale 1 moveRightLeft | navigateGUI right"
 KeyRightAlt=
 KeyRightBracket=
@@ -126,6 +126,6 @@
 KeyTab="NewHumanController changeMode"
 KeyU=""
-KeyUP="scale 1 moveFrontBack"
-KeyUnassigned="openConsole"
+KeyUP="scale 1 moveFrontBack | navigateGUI up"
+KeyUnassigned="InGameConsole openConsole"
 KeyUnderline=
 KeyUnlabeled=
Index: /code/branches/tutorial/data/gui/layouts/GraphicsMenu.layout
===================================================================
--- /code/branches/tutorial/data/gui/layouts/GraphicsMenu.layout	(revision 8050)
+++ /code/branches/tutorial/data/gui/layouts/GraphicsMenu.layout	(revision 8051)
@@ -15,76 +15,194 @@
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
             <Property Name="VertFormatting" Value="TopAligned" />
-            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2,0},{0.75,0},{0.6375,0}}" />
-            <Window Type="MenuWidgets/StaticText" Name="orxonox/Resolution" >
-                <Property Name="Text" Value="Resolution" />
-                <Property Name="InheritsAlpha" Value="False" />
-                <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.15,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/TabControl" Name="orxonox/GraphicsTabControl" >
+                <Property Name="TabHeight" Value="{0,26.4388}" />
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="VertFormatting" Value="TopAligned" />
-                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.10,0},{0.475,0},{0.65,0}}" />
-                <Window Type="MenuWidgets/Listbox" Name="orxonox/ResolutionListbox" >
+                <Property Name="TabPanePosition" Value="Top" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.925,0}}" />
+                <Window Type="DefaultWindow" Name="orxonox/Display" >
+                    <Property Name="Text" Value="Display" />
                     <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                    <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.2,0},{0.95,0},{0.95,0}}" />
-                    <Event Name="ItemSelectionChanged" Function="GraphicsMenu.GraphicsResolutionListbox_changed"/>
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution" >
+                        <Property Name="Text" Value="Resolution" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="VertFormatting" Value="TopAligned" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.025,0},{0.035,0},{0.4875,0},{0.96,0}}" />
+                        <Window Type="MenuWidgets/Checkbox" Name="orxonox/Display/Resolution/Fullscreen" >
+                            <Property Name="Text" Value="Fullscreen" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.27,0}}" />
+                            <Event Name="CheckStateChanged" Function="GraphicsMenu.callback_FullscreenCheckbox_CheckStateChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/Resolution/Combobox" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.3,0},{0.95,0},{1.2,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_ResolutionCombobox_ListSelectionAccepted" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/EditboxWidth" >
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.45,0},{0.45,0},{0.57,0}}" />
+                            <Event Name="TextChanged" Function="GraphicsMenu.callback_ResolutionEditboxWidth_TextChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/EditboxHeight" >
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.45,0},{0.95,0},{0.57,0}}" />
+                            <Event Name="TextChanged" Function="GraphicsMenu.callback_ResolutionEditboxHeight_TextChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution/x" >
+                            <Property Name="Text" Value="x" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="HorzFormatting" Value="HorzCentred" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.45,0},{0.45,0},{0.55,0},{0.57,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Button" Name="orxonox/Display/Resolution/Apply" >
+                            <Property Name="Text" Value="Apply" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.61,0},{0.75,0},{0.73,0}}" />
+                            <Event Name="Clicked" Function="GraphicsMenu.callback_Apply_Clicked" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution/AspectRatioLabel" >
+                            <Property Name="Text" Value="Aspect Ratio" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.825,0},{0.6,0},{0.95,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/AspectRatio" >
+                            <Property Name="Text" Value="1" />
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.825,0},{0.95,0},{0.95,0}}" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Theme" >
+                        <Property Name="Text" Value="Theme" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="VertFormatting" Value="TopAligned" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.035,0},{0.975,0},{0.32,0}}" />
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/Theme/Combobox" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.5,0},{0.95,0},{1.6,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_ThemeCombobox_ListSelectionAccepted" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/More" >
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.37,0},{0.975,0},{0.7,0}}" />
+                        <Window Type="MenuWidgets/Checkbox" Name="orxonox/Display/More/VSync" >
+                            <Property Name="Text" Value="VSync" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.45,0}}" />
+                            <Event Name="CheckStateChanged" Function="GraphicsMenu.callback_VSyncCheckbox_CheckStateChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/More/FSAALabel" >
+                            <Property Name="Text" Value="FSAA" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.55,0},{0.3,0},{0.9,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/More/FSAA" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.3,0},{0.55,0},{0.95,0},{2.1,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_FSAACombobox_ListSelectionAccepted" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Notice" >
+                        <Property Name="Font" Value="BlueHighway-12" />
+                        <Property Name="Text" >Changing the theme, FSAA,
+or VSync requires a restart</Property>
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.75,0},{0.975,0},{0.96,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/NoticeRed" >
+                        <Property Name="Font" Value="BlueHighway-12" />
+                        <Property Name="Text" >Restart required</Property>
+                        <Property Name="TextColours" Value="tl:FFFF0000 tr:FFFF8888 bl:FFFF8888 br:FFFFFFFF" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.75,0},{0.975,0},{0.96,0}}" />
+                    </Window>
+                </Window>
+                <Window Type="DefaultWindow" Name="orxonox/Settings" >
+                    <Property Name="Text" Value="Settings" />
+                    <Property Name="Visible" Value="False" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/FovLabel" >
+                        <Property Name="Text" Value="Vertical field of view (FOV)" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.05,0},{0.5,0},{0.12,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/FpsLimitLabel" >
+                        <Property Name="Text" Value="Maximal frame rate" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.18,0},{0.5,0},{0.25,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/ParticleLodLabel" >
+                        <Property Name="Text" Value="Particle detail level" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.31,0},{0.5,0},{0.38,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/Editbox" Name="orxonox/Settings/Fov" >
+                        <Property Name="MaxTextLength" Value="1073741823" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.03,0},{0.65,0},{0.14,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Editbox" Name="orxonox/Settings/FpsLimit" >
+                        <Property Name="MaxTextLength" Value="1073741823" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.16,0},{0.65,0},{0.27,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Combobox" Name="orxonox/Settings/ParticleLodCombobox" >
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="ClippedByParent" Value="False" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.29,0},{0.7,0},{0.725,0}}" />
+                        <Property Name="MaxEditTextLength" Value="1073741823" />
+                    </Window>
+                    <Window Type="MenuWidgets/Checkbox" Name="orxonox/Settings/MeshLodCheckbox" >
+                        <Property Name="Text" Value="Enable mesh LOD" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.44,0},{0.5,0},{0.51,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Checkbox" Name="orxonox/Settings/MotionBlurCheckbox" >
+                        <Property Name="Text" Value="Enable motion blur" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.57,0},{0.5,0},{0.64,0}}" />
+                    </Window>
                 </Window>
             </Window>
-            <Window Type="MenuWidgets/StaticText" Name="orxonox/Themes" >
-                <Property Name="Text" Value="Themes" />
-                <Property Name="InheritsAlpha" Value="False" />
-                <Property Name="HorzFormatting" Value="HorzCentred" />
-                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="VertFormatting" Value="TopAligned" />
-                <Property Name="UnifiedAreaRect" Value="{{0.525,0},{0.10,0},{0.95,0},{0.35,0}}" />
-                <Window Type="MenuWidgets/Listbox" Name="orxonox/ThemeDropBox" >
-                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                    <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.3,0},{0.95,0},{0.95,0}" />
-                    <Event Name="ItemSelectionChanged" Function="GraphicsMenu.ThemeDropBox_changed"/>
-                </Window>
-            </Window>
-            <Window Type="MenuWidgets/StaticText" Name="orxonox/Brightness" >
-                <Property Name="Text" Value="Brightness" />
-                <Property Name="InheritsAlpha" Value="False" />
-                <Property Name="HorzFormatting" Value="HorzCentred" />
-                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="VertFormatting" Value="TopAligned" />
-                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.70,0},{0.475,0},{0.85,0}}" />
-                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/BrightnessScrollbar" >
-                    <Property Name="Disabled" Value="true" />
-                    <Property Name="PageSize" Value="0" />
-                    <Property Name="StepSize" Value="0.1" />
-                    <Property Name="OverlapSize" Value="0" />
-                    <Property Name="DocumentSize" Value="1" />
-                    <Property Name="ScrollPosition" Value="0" />
-                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                    <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.6,0},{0.95,0},{0.8,0}}" />
-                    <Event Name="ThumbTrackStarted" Function="GraphicsMenu.GraphicsBrightnessScrollbar_started" />
-                    <Event Name="ThumbTrackEnded" Function="GraphicsMenu.GraphicsBrightnessScrollbar_ended" />
-                    <Event Name="ScrollPosChanged" Function="GraphicsMenu.GraphicsBrightnessScrollbar_changed" />
-                </Window>
-            </Window>
-            <Window Type="MenuWidgets/Checkbox" Name="orxonox/FullscreenCheckbox" >
-                <Property Name="Text" Value="Fullscreen" />
-                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.35,0},{0.85,0},{0.425,0}}" />
-                <Event Name="CheckStateChanged" Function="GraphicsMenu.GraphicsFullscreenCheckbox_clicked"/>
-            </Window>
-            <Window Type="MenuWidgets/StaticText" Name="orxonox/GraphicsInfo" >
-                <Property Name="Text" >
-Changes in graphics
-settings require
-a game restart.</Property>
-                <Property Name="TextColours" Value="FFFFFFFF" />
-                <Property Name="InheritsAlpha" Value="False" />
-                <Property Name="HorzFormatting" Value="HorzCentred" />
-                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="VertFormatting" Value="TopAligned" />
-                <Property Name="UnifiedAreaRect" Value="{{0.525,0},{0.425,0},{0.95,0},{0.85,0}}" />
-            </Window>
         </Window>
-        <Window Type="MenuWidgets/Button" Name="orxonox/GraphicsBackButton" >
-            <Property Name="Text" Value="Back" />
+        <Window Type="MenuWidgets/Button" Name="orxonox/GraphicsOkButton" >
+            <Property Name="Text" Value="OK" />
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
-            <Event Name="Clicked" Function="GraphicsMenu.GraphicsBackButton_clicked"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.6625,0},{0.4875,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="GraphicsMenu.callback_Ok_Clicked" />
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/GraphicsCancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.6625,0},{0.7125,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="GraphicsMenu.callback_Cancel_Clicked" />
         </Window>
     </Window>
Index: /code/branches/tutorial/data/gui/scripts/GUISheet.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/GUISheet.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/GUISheet.lua	(revision 8051)
@@ -28,4 +28,12 @@
 end
 
+-- Override this function if you want to react on keystrokes
+function P:onKeyPressed(mode)
+end
+
+-- Override this function if you want to update the gui after the window was resized
+function P:onWindowResized()
+end
+
 -- show function for the GUI
 function P:show()
@@ -77,24 +85,24 @@
 
 -- Handles key pressed while the gui sheed is displayed
-function P:keyPressed()
+function P:keyPressed(mode)
     if self.buttons then
-        if code == "208" then     -- key down
+        if mode == "down" then     -- key down
             self:moveSelectionRow(1)
-        elseif code == "200" then -- key up
+        elseif mode == "up" then -- key up
             self:moveSelectionRow(-1)
-        elseif code == "205" then -- key right
+        elseif mode == "right" then -- key right
             self:moveSelectionColumn(1)
-        elseif code == "203" then -- key left
+        elseif mode == "left" then -- key left
             self:moveSelectionColumn(-1)
-        elseif code == "28"  then -- key enter
+        elseif mode == "enter" then -- key enter or key numpad enter
             self:pressSelectedButton()
         end
     end
 
-    self.onKeyPressed()
-end
-
--- Override this function if you want to ract on keystrokes
-function P:onKeyPressed()
+    self:onKeyPressed(mode)
+end
+
+function P:windowResized()
+    self:onWindowResized()
 end
 
Index: /code/branches/tutorial/data/gui/scripts/GraphicsMenu.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/GraphicsMenu.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/GraphicsMenu.lua	(revision 8051)
@@ -1,228 +1,421 @@
 -- GraphicsMenu.lua
 
-local P = createMenuSheet("GraphicsMenu")
-
+local P = createMenuSheet("GraphicsMenu", true, TriBool.True, TriBool.True)
+
+P.resolutionList = {"custom", "640 x 480", "720 x 480", "720 x 576", "800 x 600", "1024 x 600", "1024 x 768", "1152 x 864", "1280 x 720", "1280 x 800", "1280 x 960", "1280 x 1024", "1360 x 768", "1440 x 900", "1600 x 900", "1600 x 1200", "1680 x 1050"}
 P.schemeList = {"TaharezGreen", "Orxonox"}
-
-function P.onLoad()
-    block = true
-    file = orxonox.PathConfig:getConfigPathString() .. orxonox.getConfig("GraphicsManager", "ogreConfigFile_")
-    search_mode = 0
-    f = io.open(file, "r")
-    firstline = f:read("*line")
-    rendersystem = string.sub(firstline, 15)
-    for line in f:lines() do
-        if search_mode == 0 then
-            if string.find(line, rendersystem) ~= nil then
-                search_mode = 1
-            end
+P.fsaaList = {"0", "2", "4", "8", "8 [Quality]"}
+P.particleLodList = {"None", "Low", "Normal", "High"}
+
+function P:onLoad()
+    -------------------
+    -- Button matrix --
+    -------------------
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/GraphicsOkButton"),
+            ["callback"]  = P.callback_Ok_Clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/GraphicsCancelButton"),
+            ["callback"]  = P.callback_Cancel_Clicked
+    })
+
+    -- place apply button at the bottom in the matrix, even though it's in fact at the top, to make the OK button highlighted by default
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/Display/Resolution/Apply"),
+            ["callback"]  = P.callback_Apply_Clicked
+    })
+
+    -----------------
+    -- Combo boxes --
+    -----------------
+
+    -- resolution combobox
+    local resolutionCombobox = winMgr:getWindow("orxonox/Display/Resolution/Combobox")
+    CEGUI.toCombobox(resolutionCombobox):setReadOnly(true)
+
+    for k,v in pairs(P.resolutionList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        resolutionCombobox:addItem(item)
+    end
+
+    -- themes combobox
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    CEGUI.toCombobox(themeCombobox):setReadOnly(true)
+
+    for k,v in pairs(P.schemeList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        themeCombobox:addItem(item)
+    end
+
+    -- fsaa combobox
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    CEGUI.toCombobox(fsaaCombobox):setReadOnly(true)
+
+    for k,v in pairs(P.fsaaList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        fsaaCombobox:addItem(item)
+    end
+
+    -- particle lod combobox
+    local particleLodCombobox = winMgr:getWindow("orxonox/Settings/ParticleLodCombobox")
+    CEGUI.toCombobox(particleLodCombobox):setReadOnly(true)
+
+    for k,v in pairs(P.particleLodList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        particleLodCombobox:addItem(item)
+    end
+end
+
+function P:onShow()
+    -----------------
+    -- Display tab --
+    -----------------
+
+    -- fullscreen checkbox / resolution combobox / resolution editboxes
+    self:onWindowResized()
+
+    -- apply button
+    self.updateApplyButton()
+
+    -- aspect ratio editbox
+    local aspectRatioEditbox = winMgr:getWindow("orxonox/Display/Resolution/AspectRatio")
+    local currentAspectRatio = orxonox.CommandExecutor:query("getConfig Camera aspectRatio_")
+    aspectRatioEditbox:setText(currentAspectRatio)
+
+    -- themes combobox
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    local currentTheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
+
+    for i = 0, themeCombobox:getDropList():getItemCount() - 1 do
+        local item = themeCombobox:getListboxItemFromIndex(i)
+        themeCombobox:setItemSelectState(item, (item:getText() == currentTheme))
+    end
+
+    -- vsync checkbox
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    CEGUI.toCheckbox(vsyncCheckbox):setSelected(hasVSync)
+
+    -- fsaa combobox
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+
+    for i = 0, fsaaCombobox:getDropList():getItemCount() - 1 do
+        local item = fsaaCombobox:getListboxItemFromIndex(i)
+        fsaaCombobox:setItemSelectState(item, (item:getText() == currentFSAAMode))
+    end
+
+    -- notice
+    self:updateRedLabel()
+
+    ------------------
+    -- Settings tab --
+    ------------------
+
+    -- fov editbox
+    local fovEditbox = winMgr:getWindow("orxonox/Settings/Fov")
+    local currentFov = orxonox.CommandExecutor:query("getConfig Camera fov_")
+    fovEditbox:setText(currentFov)
+
+    -- fps limit editbox
+    local fpsEditbox = winMgr:getWindow("orxonox/Settings/FpsLimit")
+    local currentFpsLimit = orxonox.CommandExecutor:query("getConfig GraphicsSettings fpsLimit")
+    fpsEditbox:setText(currentFpsLimit)
+
+    -- particle lod combobox
+    local particleLodCombobox = winMgr:getWindow("orxonox/Settings/ParticleLodCombobox")
+    local currentParticleLod = orxonox.CommandExecutor:query("getConfig GraphicsSettings particlesDetailLevel")
+
+    if currentParticleLod == "" then
+        particleLodCombobox:disable()
+    else
+        particleLodCombobox:enable()
+
+        for i = 0, particleLodCombobox:getDropList():getItemCount() - 1 do
+            local item = particleLodCombobox:getListboxItemFromIndex(i)
+            particleLodCombobox:setItemSelectState(item, (tostring(i) == currentParticleLod))
         end
-        if search_mode == 1 then
-            if string.sub(line, 1, 11) == "Full Screen" then
-                if string.sub(line, 13) == "Yes" then
-                    fullscreen = true
-                else
-                    fullscreen = false
-                end
-            end
-            if string.sub(line, 1, 10) == "Video Mode" then
-                if string.match(line, "@") == "@" then
-                    resolution = string.sub(line, 12, string.find(line, "@")-2)
-                else
-                    resolution = string.sub(line, 12)
-                end
-                break
-            end
+    end
+
+    -- mesh lod checkbox
+    local meshLodCheckbox = winMgr:getWindow("orxonox/Settings/MeshLodCheckbox")
+    local hasMeshLod = orxonox.CommandExecutor:query("getConfig GraphicsSettings enableMeshLoD")
+    if hasMeshLod == "true" then
+        hasMeshLod = true
+    elseif hasMeshLod == "false" then
+        hasMeshLod = false
+    end
+    CEGUI.toCheckbox(meshLodCheckbox):setSelected(hasMeshLod)
+
+    -- motion blur checkbox
+    local motionBlurCheckbox = winMgr:getWindow("orxonox/Settings/MotionBlurCheckbox")
+    local hasMotionBlur = orxonox.CommandExecutor:query("getConfig GraphicsSettings enableMotionBlur")
+    if hasMotionBlur == "true" then
+        hasMotionBlur = true
+    elseif hasMotionBlur == "false" then
+        hasMotionBlur = false
+    end
+    CEGUI.toCheckbox(motionBlurCheckbox):setSelected(hasMotionBlur)
+end
+
+function P:onWindowResized()
+    -- fullscreen checkbox
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local isFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+    CEGUI.toCheckbox(fullscreenCheckbox):setSelected(isFullscreen)
+
+    -- resolution combobox
+    local resolutionCombobox = winMgr:getWindow("orxonox/Display/Resolution/Combobox")
+
+    local currentWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    local currentHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+
+    if P.forceResolutionEditboxes then
+        currentWidth = P.newWidth
+        currentHeight = P.newHeight
+        P.forceResolutionEditboxes = false
+    end
+
+    local currentResolution = currentWidth .. " x " .. currentHeight
+
+    for i = 0, resolutionCombobox:getDropList():getItemCount() - 1 do
+        local item = resolutionCombobox:getListboxItemFromIndex(i)
+        resolutionCombobox:setItemSelectState(item, item:getText() == currentResolution)
+    end
+
+    -- resolution editboxes
+    self.updateResolutionEditboxes()
+end
+
+----------------------
+-- Helper functions --
+----------------------
+
+-- updates the text of the resolution checkboxes and checks if they should be enabled (only if the "custom" resolution was selected)
+function P.updateResolutionEditboxes()
+    -- resolution combobox
+    local resolutionCombobox = winMgr:getWindow("orxonox/Display/Resolution/Combobox")
+
+    local currentWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    local currentHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+
+    -- resolution editboxes
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+    widthEditbox:disable()
+    heightEditbox:disable()
+
+    -- selected combobox item
+    local item = resolutionCombobox:getSelectedItem()
+    if item then
+        local itemText = item:getText()
+        if itemText ~= "custom" then
+            currentWidth = string.sub(itemText, 1, string.find(itemText, "x") - 2)
+            currentHeight = string.sub(itemText, string.find(itemText, "x") + 2)
+        else
+            widthEditbox:enable()
+            heightEditbox:enable()
         end
     end
-    f:close()
-    local fullscreenwindow = tolua.cast(winMgr:getWindow("orxonox/FullscreenCheckbox"),"CEGUI::Checkbox")
-    fullscreenwindow:setSelected(fullscreen)
-    listboxwindow = winMgr:getWindow("orxonox/ResolutionListbox")
-    local resolutionList = {}
-    table.insert(resolutionList, "640 x 480")
-    table.insert(resolutionList, "720 x 480")
-    table.insert(resolutionList, "720 x 576")
-    table.insert(resolutionList, "800 x 480")
-    table.insert(resolutionList, "800 x 600")
-    table.insert(resolutionList, "1024 x 480")
-    table.insert(resolutionList, "1024 x 600")
-    table.insert(resolutionList, "1024 x 768")
-    table.insert(resolutionList, "1152 x 864")
-    table.insert(resolutionList, "1280 x 720")
-    table.insert(resolutionList, "1280 x 768")
-    table.insert(resolutionList, "1440 x 900")
-    for k,v in pairs(resolutionList) do
-        item = CEGUI.createListboxTextItem(v)
-        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
-        CEGUI.toListbox(listboxwindow):addItem(item)
-    end
-    if resolution == "640 x 480" then
-        listboxwindow:setItemSelectState(0,true)
-    elseif resolution == "720 x 480" then
-        listboxwindow:setItemSelectState(1,true)
-    elseif resolution == "720 x 576" then
-        listboxwindow:setItemSelectState(2,true)
-    elseif resolution == "800 x 480" then
-        listboxwindow:setItemSelectState(3,true)
-    elseif resolution == "800 x 600" then
-        listboxwindow:setItemSelectState(4,true)
-    elseif resolution == "1024 x 480" then
-        listboxwindow:setItemSelectState(5,true)
-    elseif resolution == "1024 x 600" then
-        listboxwindow:setItemSelectState(6,true)
-    elseif resolution == "1024 x 768" then
-        listboxwindow:setItemSelectState(7,true)
-    elseif resolution == "1152 x 864" then
-        listboxwindow:setItemSelectState(8,true)
-    elseif resolution == "1280 x 720" then
-        listboxwindow:setItemSelectState(9,true)
-    elseif resolution == "1280 x 768" then
-        listboxwindow:setItemSelectState(10,true)
-    elseif resolution == "1440 x 900" then
-        listboxwindow:setItemSelectState(11,true)
-    end
-    scrollbar_active = false
-    block = false
-
-    P:setButton(1, 1, {
-            ["button"] = winMgr:getWindow("orxonox/GraphicsBackButton"),
-            ["callback"]  = P.GraphicsBackButton_clicked
-    })
-
-    local dropbox = winMgr:getWindow("orxonox/ThemeDropBox")
-    local scheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
-    for k,v in pairs(P.schemeList) do
-        local item = CEGUI.createListboxTextItem(P.schemeList[k])
-        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
-        CEGUI.toListbox(dropbox):addItem(item)
-        if v == scheme then
-            dropbox:setItemSelectState(item, true)
-        end
-    end
-
-end
-
-function P.ThemeDropBox_changed(e)
-    local dropbox = winMgr:getWindow("orxonox/ThemeDropBox")
-    local listbox = CEGUI.toListbox(dropbox)
-    local choice = listbox:getFirstSelectedItem()
-    local index = 0
-    if choice ~= nil then
-        index = listbox:getItemIndex(choice)
-    end
-    orxonox.CommandExecutor:execute("config GUIManager guiScheme_ " .. P.schemeList[index+1])
-end
-
-function P.GraphicsResolutionListbox_changed(e)
-    if listboxwindow:isItemSelected(0) then
-        resolution = "640 x 480"
-    elseif listboxwindow:isItemSelected(1) then
-        resolution = "720 x 480"
-    elseif listboxwindow:isItemSelected(2) then
-        resolution = "720 x 576"
-    elseif listboxwindow:isItemSelected(3) then
-        resolution = "800 x 480"
-    elseif listboxwindow:isItemSelected(4) then
-        resolution = "800 x 600"
-    elseif listboxwindow:isItemSelected(5) then
-        resolution = "1024 x 480"
-    elseif listboxwindow:isItemSelected(6) then
-        resolution = "1024 x 600"
-    elseif listboxwindow:isItemSelected(7) then
-        resolution = "1024 x 768"
-    elseif listboxwindow:isItemSelected(8) then
-        resolution = "1152 x 864"
-    elseif listboxwindow:isItemSelected(9) then
-        resolution = "1280 x 720"
-    elseif listboxwindow:isItemSelected(10) then
-        resolution = "1280 x 768"
-    elseif listboxwindow:isItemSelected(11) then
-        resolution = "1440 x 900"
-    end
-    search_mode = 0
-    f = io.open(file, "r")
-    firstline = f:read("*line")
-    text = firstline .. "\n"
-    rendersystem = string.sub(firstline, 15)
-    for line in f:lines() do
-        if search_mode == 0 then
-            if string.find(line, rendersystem) ~= nil then
-                search_mode = 1
-            end
-        end
-        if search_mode == 1 then
-            if string.sub(line, 1, 10) == "Video Mode" then
-                if string.match(line, "@") == "@" then
-                    line = "Video Mode=" .. resolution .. string.sub(line, string.find(line, "@")-1)
-                else
-                    line = "Video Mode=" .. resolution
-                end
-                search_mode = 2
-            end
-        end
-        text = text .. line .. "\n"
-    end
-    f:close()
-    f = io.open(file, "w")
-    f:write(text)
-    f:close()
-end
-
-function P.GraphicsBrightnessScrollbar_changed(e)
-    if scrollbar_active == false then
-        -- brightness
-        logMessage(0, "event: brightness")
-    end
-end
-
-function P.GraphicsBrightnessScrollbar_started(e)
-    scrollbar_active = true
-end
-
-function P.GraphicsBrightnessScrollbar_ended(e)
-    -- brightness
-    logMessage(0, "event: brightness")
-    scrollbar_active = false
-end
-
-function P.GraphicsFullscreenCheckbox_clicked(e)
-    if block == false then
-        search_mode = 0
-        f = io.open(file, "r")
-        firstline = f:read("*line")
-        text = firstline .. "\n"
-        rendersystem = string.sub(firstline, 15)
-        for line in f:lines() do
-            if search_mode == 0 then
-                if string.find(line, rendersystem) ~= nil then
-                    search_mode = 1
-                end
-            end
-            if search_mode == 1 then
-                if string.sub(line, 1, 11) == "Full Screen" then
-                    if fullscreen == true then
-                        line = "Full Screen=No"
-                        fullscreen = false
-                    else
-                        line = "Full Screen=Yes"
-                        fullscreen = true
-                    end
-                    search_mode = 2
-                end
-            end
-            text = text .. line .. "\n"
-        end
-        f:close()
-        f = io.open(file, "w")
-        f:write(text)
-        f:close()
-    end
-end
-
-function P.GraphicsBackButton_clicked(e)
+
+    widthEditbox:setText(currentWidth)
+    heightEditbox:setText(currentHeight)
+end
+
+-- checks if the apply button should be enabled or disabled (only enabled if the current settings are different from the selected values)
+function P.updateApplyButton()
+    -- fullscreen checkbox
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local isFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+    local fullscreenChanged = (isFullscreen ~= CEGUI.toCheckbox(fullscreenCheckbox):isSelected())
+
+    -- resolution editboxes
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+    local currentWidth = tostring(orxonox.GraphicsManager:getInstance():getWindowWidth())
+    local currentHeight = tostring(orxonox.GraphicsManager:getInstance():getWindowHeight())
+    local widthChanged = (currentWidth ~= widthEditbox:getText())
+    local heightChanged = (currentHeight ~= heightEditbox:getText())
+    local resolutionEditboxesEnabled = not widthEditbox:isDisabled()
+
+    -- apply button
+    local applyButton = winMgr:getWindow("orxonox/Display/Resolution/Apply")
+
+    if fullscreenChanged or widthChanged or heightChanged or resolutionEditboxesEnabled then
+        applyButton:enable()
+    else
+        applyButton:disable()
+    end
+end
+
+function P.updateRedLabel()
+    -- theme
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    local currentTheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
+    local themeChanged = (currentTheme ~= themeCombobox:getText())
+
+    -- vsync
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    local vsyncChanged = (hasVSync ~= CEGUI.toCheckbox(vsyncCheckbox):isSelected())
+
+    -- fsaa
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+    local fsaaChanged = (currentFSAAMode ~= fsaaCombobox:getText())
+
+    local needRestart = themeChanged or vsyncChanged or fsaaChanged
+
+    local notice = winMgr:getWindow("orxonox/Display/Notice")
+    notice:setVisible(not needRestart)
+    local noticeRed = winMgr:getWindow("orxonox/Display/NoticeRed")
+    noticeRed:setVisible(needRestart)
+end
+
+---------------------
+-- Event callbacks --
+---------------------
+
+-- resolution
+
+function P.callback_FullscreenCheckbox_CheckStateChanged(e)
+    P.updateApplyButton()
+end
+
+function P.callback_ResolutionCombobox_ListSelectionAccepted(e)
+    P.updateResolutionEditboxes()
+end
+
+function P.callback_ResolutionEditboxWidth_TextChanged(e)
+    P.updateApplyButton()
+end
+
+function P.callback_ResolutionEditboxHeight_TextChanged(e)
+    P.updateApplyButton()
+end
+
+-- theme
+
+function P.callback_ThemeCombobox_ListSelectionAccepted(e)
+    P.updateRedLabel()
+end
+
+-- vsync
+
+function P.callback_VSyncCheckbox_CheckStateChanged(e)
+    P.updateRedLabel()
+end
+
+-- fsaa
+
+function P.callback_FSAACombobox_ListSelectionAccepted(e)
+    P.updateRedLabel()
+end
+
+-- buttons
+
+function P.callback_Apply_Clicked(e)
+    -- resolution
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local checkedFullscreen = tostring(CEGUI.toCheckbox(fullscreenCheckbox):isSelected())
+
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+
+    P.newWidth = widthEditbox:getText()
+    P.newHeight = heightEditbox:getText()
+    P.forceResolutionEditboxes = true
+
+    -- start revert timer
+    P.oldWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    P.oldHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+    P.oldFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+
+    P.revertTimerHandle = orxonox.CommandExecutor:query("delayreal 10 {hideGUI DecisionPopup; GraphicsManager setScreenResolution " .. P.oldWidth .. " " .. P.oldHeight .. " " .. tostring(P.oldFullscreen) .. "; config Core lastLevelTimestamp_ [expr [getConfig Core ogreConfigTimestamp_] + 1]}")
+
+    -- change settings
+    orxonox.CommandExecutor:execute("GraphicsManager setScreenResolution " .. P.newWidth .. " " .. P.newHeight .. " " .. checkedFullscreen)
+
+    P.updateApplyButton()
+
+    -- prompt for confirmation
+    openDecisionPopup("Do you want to keep these settings? (Settings will be reverted in 10 seconds if not accepted)", GraphicsMenu.callback_ApplyDecisionPopup)
+    if checkedFullscreen then
+        showCursor()
+    end
+end
+
+function P.callback_ApplyDecisionPopup(pressedOK)
+    orxonox.CommandExecutor:execute("killdelay " .. P.revertTimerHandle)
+
+    if not pressedOK then
+        orxonox.CommandExecutor:execute("GraphicsManager setScreenResolution " .. P.oldWidth .. " " .. P.oldHeight .. " " .. tostring(P.oldFullscreen))
+        P:onShow()
+    end
+
+    -- update timestamp to avoid showing the ogre config dialog again after the user accepted or reverted the resolution
+    orxonox.CommandExecutor:execute("config Core lastLevelTimestamp_ [expr [getConfig Core ogreConfigTimestamp_] + 1]")
+end
+
+function P.callback_Ok_Clicked(e)
+    -- aspect ratio
+    local aspectRatioEditbox = winMgr:getWindow("orxonox/Display/Resolution/AspectRatio")
+    orxonox.CommandExecutor:execute("config Camera aspectRatio_ " .. aspectRatioEditbox:getText())
+
+    -- theme
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    orxonox.CommandExecutor:execute("config GUIManager guiScheme_ " .. themeCombobox:getText())
+
+    -- vsync
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    if hasVSync ~= CEGUI.toCheckbox(vsyncCheckbox):isSelected() then
+        orxonox.CommandExecutor:execute("GraphicsManager setVSync " .. tostring(CEGUI.toCheckbox(vsyncCheckbox):isSelected()))
+    end
+
+    -- fsaa
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+    if currentFSAAMode ~= fsaaCombobox:getText() then
+        orxonox.CommandExecutor:execute("GraphicsManager setFSAA {" .. fsaaCombobox:getText() .. "}") -- enclose argument in { ... } because it can contain [brackets] (conflicts with tcl)
+    end
+
+    -- fov
+    local fovEditbox = winMgr:getWindow("orxonox/Settings/Fov")
+    orxonox.CommandExecutor:execute("config Camera fov_ " .. fovEditbox:getText())
+
+    -- fps limit
+    local fpsEditbox = winMgr:getWindow("orxonox/Settings/FpsLimit")
+    orxonox.CommandExecutor:execute("config GraphicsSettings fpsLimit " .. fpsEditbox:getText())
+
+    -- particle lod
+    local particleLodCombobox = winMgr:getWindow("orxonox/Settings/ParticleLodCombobox")
+    local item = particleLodCombobox:getSelectedItem()
+    if item then
+        orxonox.CommandExecutor:execute("config GraphicsSettings particlesDetailLevel " .. particleLodCombobox:getItemIndex(item))
+    end
+
+    -- mesh lod
+    local meshLodCheckbox = winMgr:getWindow("orxonox/Settings/MeshLodCheckbox")
+    orxonox.CommandExecutor:execute("config GraphicsSettings enableMeshLoD " .. tostring(CEGUI.toCheckbox(meshLodCheckbox):isSelected()))
+
+    -- motion blur
+    local motionBlurCheckbox = winMgr:getWindow("orxonox/Settings/MotionBlurCheckbox")
+    orxonox.CommandExecutor:execute("config GraphicsSettings enableMotionBlur " .. tostring(CEGUI.toCheckbox(motionBlurCheckbox):isSelected()))
+
     hideMenuSheet(P.name)
 end
 
+function P.callback_Cancel_Clicked(e)
+    hideMenuSheet(P.name)
+end
+
 return P
 
Index: /code/branches/tutorial/data/gui/scripts/HostMenu.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/HostMenu.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/HostMenu.lua	(revision 8051)
@@ -28,4 +28,11 @@
 
 function P.onShow()
+    if P.showAll ~= orxonox.GUIManager:inDevMode() then
+        local window = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+        local button = tolua.cast(window,"CEGUI::Checkbox")
+        P.showAll = not P.showAll
+        button:setSelected(P.showAll)
+    end
+
     if P.multiplayerMode == "startServer" then
         local window = winMgr:getWindow("orxonox/HostMenuHostButton")
Index: /code/branches/tutorial/data/gui/scripts/KeyBindMenu.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/KeyBindMenu.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/KeyBindMenu.lua	(revision 8051)
@@ -26,5 +26,5 @@
     table.insert(commandList, "NewHumanController changeMode")
     table.insert(commandList, "switchCamera")
-    table.insert(commandList, "openConsole")
+    table.insert(commandList, "InGameConsole openConsole")
     table.insert(commandList, "OverlayGroup toggleVisibility Debug")
     table.insert(commandList, "OverlayGroup toggleVisibility Stats")
Index: /code/branches/tutorial/data/gui/scripts/MenuSheet.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/MenuSheet.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/MenuSheet.lua	(revision 8051)
@@ -16,5 +16,5 @@
     newSheet.bHidePrevious  = handleDefArg(_bHidePrevious,  true)
     newSheet.tShowCursor    = handleDefArg(_tShowCusor,     TriBool.True)
-    newSheet.tUseKeyboard   = handleDefArg(_tUseKeyboard,   TriBool.True)
+    newSheet.tUseKeyboard   = handleDefArg(_tUseKeyboard,   TriBool.Dontcare)
     newSheet.bBlockJoyStick = handleDefArg(_bBlockJoyStick, false)
 
Index: /code/branches/tutorial/data/gui/scripts/MiscConfigMenu.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/MiscConfigMenu.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/MiscConfigMenu.lua	(revision 8051)
@@ -35,4 +35,5 @@
     table.insert(P.commandList, "HumanPlayer nick_")
     table.insert(P.commandList, "ChatOverlay displayTime_")
+    table.insert(P.commandList, "Core bDevMode_")
 
     P.nameList = {}
@@ -54,4 +55,5 @@
     table.insert(P.nameList, "Playername")
     table.insert(P.nameList, "Chat: display time")
+    table.insert(P.nameList, "Developer's Mode")
 
     P.linesList = {}
Index: /code/branches/tutorial/data/gui/scripts/SheetManager.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/SheetManager.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/SheetManager.lua	(revision 8051)
@@ -5,28 +5,23 @@
 local activeMenuSheets = {size = 0, topSheetTuple = nil}
 local menuSheetsRoot = guiMgr:getMenuRootWindow()
-local bInGameConsoleClosed = false
 local mainMenuLoaded = false
-orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "KeyDown", "keyPressed")
-
------------------------
---- Local functions ---
------------------------
-
-local function hideCursor()
-    if cursor:isVisible() then
-        cursor:hide()
-    end
-end
-
-local function showCursor()
-    if not cursor:isVisible() and inputMgr:isMouseExclusive() then
-        cursor:show()
-    end
-end
-
+--orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "KeyDown", "keyPressed")
+orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "Sized", "windowResized")
 
 ------------------------
 --- Global functions ---
 ------------------------
+
+function hideCursor()
+    if cursor:isVisible() then
+        cursor:hide()
+    end
+end
+
+function showCursor()
+    if not cursor:isVisible() and inputMgr:isMouseExclusive() then
+        cursor:show()
+    end
+end
 
 -- Loads the GUI with the specified name
@@ -93,5 +88,6 @@
         ["sheet"]          = menuSheet,
         ["bHidePrevious"]  = bHidePrevious,
-        ["bNoInput"]       = bNoInput
+        ["bNoInput"]       = bNoInput,
+        ["name"]           = name
     }
     table.insert(activeMenuSheets, sheetTuple) -- indexed array access
@@ -135,4 +131,8 @@
     if previous and previous.pressedEnter and menuSheet:hasSelection() == false then
         menuSheet:setSelectionNear(1, 1)
+    end
+
+    if activeMenuSheets.size > 0 then
+        guiMgr:guisActiveChanged(true)
     end
 
@@ -207,4 +207,8 @@
     end
 
+    if activeMenuSheets.size == 0 then
+        guiMgr:guisActiveChanged(false)
+    end
+
     sheetTuple.sheet:quit()
 end
@@ -220,11 +224,5 @@
     -- HUGE, very HUGE hacks!
 
-    -- If the InGameConsole is active, ignore the ESC command.
-    if bInGameConsoleClosed == true then
-        bInGameConsoleClosed = false
-        return
-    end
-
-    -- Count the number of sheets that don't need input till the first that does.
+    -- Count the number of sheets that don't need input until the first that does.
     local counter = noInputSheetIndex()
 
@@ -240,17 +238,28 @@
 end
 
-function keyPressed(e)
-    local we = tolua.cast(e, "CEGUI::KeyEventArgs")
+-- Function to navigate the GUI, is called by the GUIManager, whenever a relevant key is pressed.
+-- The mode specifies the action to be taken.
+function navigateGUI(mode)
     local sheet = activeMenuSheets[activeMenuSheets.size]
-    code = tostring(we.scancode)
-    -- Some preprocessing
-    if not mainMenuLoaded and not sheet.bNoInput then
-        if code == "1" then
-            keyESC()
-        elseif code == "0"then
-            orxonox.CommandExecutor:execute("openConsole")
-        end
-    end
-    sheet.sheet:keyPressed()
+    sheet.sheet:keyPressed(mode)
+end
+
+function windowResized(e)
+    for name, sheet in pairs(loadedSheets) do
+        if orxonox.GraphicsManager:getInstance():isFullScreen() or sheet.tShowCursor == TriBool.False then
+            inputMgr:setMouseExclusive(sheet.inputState, TriBool.True)
+        else
+            inputMgr:setMouseExclusive(sheet.inputState, TriBool.False)
+        end
+    end
+    local sheetTuple = activeMenuSheets[activeMenuSheets.size]
+    if sheetTuple then
+        if orxonox.GraphicsManager:getInstance():isFullScreen() and sheetTuple.sheet.tShowCursor ~= TriBool.False then
+            showCursor()
+        else
+            hideCursor()
+        end
+        sheetTuple.sheet:windowResized()
+    end
 end
 
@@ -279,6 +288,12 @@
 end
 
-function inGameConsoleClosed()
-    bInGameConsoleClosed = not bInGameConsoleClosed;
+function getGUIFirstActive(name, bHidePrevious, bNoInput)
+    local sheet = activeMenuSheets.topSheetTuple
+    -- If the topmost gui sheet has the input name
+    if sheet ~= nil and sheet.name == name then
+        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, false);
+    else
+        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, true);
+    end
 end
 
Index: /code/branches/tutorial/data/gui/scripts/SingleplayerMenu.lua
===================================================================
--- /code/branches/tutorial/data/gui/scripts/SingleplayerMenu.lua	(revision 8050)
+++ /code/branches/tutorial/data/gui/scripts/SingleplayerMenu.lua	(revision 8051)
@@ -25,4 +25,14 @@
 end
 
+function P.onShow()
+    if P.showAll ~= orxonox.GUIManager:inDevMode() then
+        local window = winMgr:getWindow("orxonox/SingleplayerShowAllCheckbox")
+        local button = tolua.cast(window,"CEGUI::Checkbox")
+        P.showAll = not P.showAll
+        button:setSelected(P.showAll)
+        P.createLevelList()
+    end
+end
+
 function P.createLevelList()
     P.levelList = {}
@@ -44,6 +54,4 @@
         index = index + 1
     end
-    --TODO: Reintroduce sorting, if needed. At the moment it's sorted by filename.
-    --table.sort(levelList)
     for k,v in pairs(P.levelList) do
         local item = CEGUI.createListboxTextItem(v:getName())
Index: /code/branches/tutorial/data/levels/presentation09.oxw
===================================================================
--- /code/branches/tutorial/data/levels/presentation09.oxw	(revision 8050)
+++ /code/branches/tutorial/data/levels/presentation09.oxw	(revision 8051)
@@ -1,5 +1,5 @@
 <LevelInfo
- name = "Presentation X"
- description = "1st Presentation level for Orxonox Convention X"
+ name = "Presentation X 3rd"
+ description = "3rd Presentation level for Orxonox Convention X"
  tags = "presentation"
 />
Index: /code/branches/tutorial/data/levels/presentationFS102.oxw
===================================================================
--- /code/branches/tutorial/data/levels/presentationFS102.oxw	(revision 8050)
+++ /code/branches/tutorial/data/levels/presentationFS102.oxw	(revision 8051)
@@ -1,4 +1,4 @@
 <LevelInfo
- name = "Presentation XI FPS"
+ name = "Presentation XI FPS 1st"
  description = "2nd Presentation level for Orxonox Convention XI, FPS"
  tags = "presentation"
Index: /code/branches/tutorial/data/levels/presentationFS10Ed.oxw
===================================================================
--- /code/branches/tutorial/data/levels/presentationFS10Ed.oxw	(revision 8050)
+++ /code/branches/tutorial/data/levels/presentationFS10Ed.oxw	(revision 8051)
@@ -1,4 +1,4 @@
 <LevelInfo
- name = "Presentation XI FPS"
+ name = "Presentation XI FPS 2nd"
  description = "3rd Presentation level for Orxonox Convention XI, FPS"
  tags = "presentation"
Index: /code/branches/tutorial/data/levels/presentationHS09.oxw
===================================================================
--- /code/branches/tutorial/data/levels/presentationHS09.oxw	(revision 8050)
+++ /code/branches/tutorial/data/levels/presentationHS09.oxw	(revision 8051)
@@ -1,4 +1,4 @@
 <LevelInfo
- name = "Presentation X"
+ name = "Presentation X 1st"
  description = "1st Presentation level for Orxonox Convention X"
  tags = "presentation"
Index: /code/branches/tutorial/data/levels/presentationHS09b.oxw
===================================================================
--- /code/branches/tutorial/data/levels/presentationHS09b.oxw	(revision 8050)
+++ /code/branches/tutorial/data/levels/presentationHS09b.oxw	(revision 8051)
@@ -1,4 +1,4 @@
 <LevelInfo
- name = "Presentation X"
+ name = "Presentation X 2nd"
  description = "2nd Presentation level for Orxonox Convention X"
  tags = "presentation"
Index: /code/branches/tutorial/data/overlays/debug.oxo
===================================================================
--- /code/branches/tutorial/data/overlays/debug.oxo	(revision 8050)
+++ /code/branches/tutorial/data/overlays/debug.oxo	(revision 8051)
@@ -68,5 +68,5 @@
     <PauseNotice
      name     = "pausenotice"
-     position = "0.5, 0.3"
+     position = "0.5, 0.1"
      font     = "VeraMono"
      textsize = 0.03
Index: /code/branches/tutorial/src/libraries/core/CMakeLists.txt
===================================================================
--- /code/branches/tutorial/src/libraries/core/CMakeLists.txt	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/CMakeLists.txt	(revision 8051)
@@ -80,4 +80,5 @@
     Game.h
     GameMode.h
+    GraphicsManager.h
     GUIManager.h
     Loader.h
Index: /code/branches/tutorial/src/libraries/core/Core.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/Core.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/Core.cc	(revision 8051)
@@ -208,6 +208,10 @@
 #ifdef ORXONOX_RELEASE
         const unsigned int defaultLevelLogFile = 3;
+        SetConfigValue(bDevMode_, false)
+            .description("Developer mode. If not set, hides some things from the user to not confuse him.");
 #else
         const unsigned int defaultLevelLogFile = 4;
+        SetConfigValue(bDevMode_, true)
+            .description("Developer mode. If not set, hides some things from the user to not confuse him.");
 #endif
         SetConfigValueExternal(softDebugLevelLogFile_, "OutputHandler", "softDebugLevelLogFile", defaultLevelLogFile)
Index: /code/branches/tutorial/src/libraries/core/Core.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/Core.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/Core.h	(revision 8051)
@@ -91,4 +91,7 @@
                 { return this->ogreConfigTimestamp_; }
 
+            inline bool inDevMode(void) const
+                { return this->bDevMode_; }
+
         private:
             Core(const Core&); //!< Don't use (undefined symbol)
@@ -130,4 +133,5 @@
             long long                     lastLevelTimestamp_;         ///< Timestamp when the last level was started
             long long                     ogreConfigTimestamp_;        ///< Timestamp wehen the ogre config level was modified
+            bool                          bDevMode_;                   //!< Developers bit. If set to false, some options are not available as to not confuse the normal user.
 
             static Core*                  singletonPtr_s;
Index: /code/branches/tutorial/src/libraries/core/GUIManager.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/GUIManager.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/GUIManager.cc	(revision 8051)
@@ -103,6 +103,17 @@
     /*static*/ const std::string GUIManager::defaultScheme_ = "TaharezGreen";
 
+    static const std::string __CC_navigateGUI_name = "navigateGUI";
+
     SetConsoleCommand("showGUI", &GUIManager::showGUI).defaultValue(1, false).defaultValue(2, false);
     SetConsoleCommand("hideGUI", &GUIManager::hideGUI);
+    SetConsoleCommand("toggleGUI", &GUIManager::toggleGUI).defaultValue(1, false).defaultValue(2, false);
+    SetConsoleCommand(__CC_navigateGUI_name, &GUIManager::navigateGUI).deactivate();
+
+    //! Strings that specify modes for the GUI navigation.
+    /*static*/ const std::string GUIManager::NAVIGATE_UP = "up";
+    /*static*/ const std::string GUIManager::NAVIGATE_DOWN = "down";
+    /*static*/ const std::string GUIManager::NAVIGATE_LEFT = "left";
+    /*static*/ const std::string GUIManager::NAVIGATE_RIGHT = "right";
+    /*static*/ const std::string GUIManager::NAVIGATE_ENTER = "enter";
 
     /**
@@ -282,4 +293,27 @@
     {
         GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
+    }
+
+    /**
+    @brief
+        Toggles specified GUI.
+        If the GUI with the input name is already shown and on the top, it is hidden, else it is shown.
+    */
+    /*static*/ void GUIManager::toggleGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
+    {
+        GUIManager::getInstance().executeCode("getGUIFirstActive(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
+    }
+
+    /**
+    @brief
+        Helper method to toggle a specified GUI.
+        Is called by lua.
+    */
+    void GUIManager::toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show)
+    {
+        if(show)
+            GUIManager::showGUI(name, bHidePrevious, bNoInput);
+        else
+            GUIManager::hideGUI(name);
     }
 
@@ -340,4 +374,41 @@
             this->rootWindow_->setProperty("Alpha", "1.0");
         this->rootWindow_->setProperty("Image", image);
+    }
+
+    /**
+    @brief
+        Method to navigate the GUI, by specifying the mode of navigation.
+    @param mode
+        The mode of navigation, at this point can be either 'up', 'down', 'left', 'right' or 'enter'.
+    */
+    /*static*/ void GUIManager::navigateGUI(const std::string& mode)
+    {
+        if(mode == NAVIGATE_UP)
+            GUIManager::getInstance().executeCode("navigateGUI(\"" + NAVIGATE_UP + "\")");
+        else if(mode == NAVIGATE_DOWN)
+            GUIManager::getInstance().executeCode("navigateGUI(\"" + NAVIGATE_DOWN + "\")");
+        else if(mode == NAVIGATE_LEFT)
+            GUIManager::getInstance().executeCode("navigateGUI(\"" + NAVIGATE_LEFT + "\")");
+        else if(mode == NAVIGATE_RIGHT)
+            GUIManager::getInstance().executeCode("navigateGUI(\"" + NAVIGATE_RIGHT + "\")");
+        else if(mode == NAVIGATE_ENTER)
+            GUIManager::getInstance().executeCode("navigateGUI(\"" + NAVIGATE_ENTER + "\")");
+    }
+
+    /**
+    @brief
+        Is called by lua to change whether there are any GUIs active at the moment.
+    @param active
+        Whether GUIs are active.
+    */
+    void GUIManager::guisActiveChanged(bool active)
+    {
+        if(this->GUIsActive_ == active)
+            return;
+        this->GUIsActive_ = active;
+        if(this->GUIsActive_)
+            ModifyConsoleCommand(__CC_navigateGUI_name).activate();
+        else
+            ModifyConsoleCommand(__CC_navigateGUI_name).deactivate();
     }
 
Index: /code/branches/tutorial/src/libraries/core/GUIManager.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/GUIManager.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/GUIManager.h	(revision 8051)
@@ -49,4 +49,5 @@
 #include "util/Singleton.h"
 #include "input/InputHandler.h"
+#include "Core.h"
 #include "OrxonoxClass.h"
 #include "WindowEventListener.h"
@@ -88,7 +89,18 @@
         void showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious = false, bool bNoInput = false);
         static void hideGUI(const std::string& name);
+        static void toggleGUI(const std::string& name, bool bHidePrevious = false, bool bNoInput = false);
+        void toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show); // tolua_export
         void keyESC();
         void setBackgroundImage(const std::string& imageSet, const std::string imageName); // tolua_export
         void setBackgroundImage(const std::string& image);
+
+        static void navigateGUI(const std::string& mode);
+        void guisActiveChanged(bool active); // tolua_export
+
+        /**
+        @brief Helper method to get the developer's mode without having to export Core.h.
+        @see Core::inDevMode
+        */
+        static bool inDevMode(void) { return Core::getInstance().inDevMode(); } // tolua_export
 
         //! Creates a new InputState to be used with a GUI Sheet
@@ -122,4 +134,12 @@
         template <typename FunctionType>
         bool protectedCall(FunctionType function);
+
+        static const std::string NAVIGATE_UP;
+        static const std::string NAVIGATE_DOWN;
+        static const std::string NAVIGATE_LEFT;
+        static const std::string NAVIGATE_RIGHT;
+        static const std::string NAVIGATE_ENTER;
+
+        bool GUIsActive_; //!< Whether there are any GUIs active at a given moment.
 
         // keyHandler functions
Index: /code/branches/tutorial/src/libraries/core/Game.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/Game.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/Game.cc	(revision 8051)
@@ -61,8 +61,8 @@
     static void printFPS()
         { COUT(0) << Game::getInstance().getAvgFPS() << std::endl; }
-    SetConsoleCommand("printFPS", &printFPS);
+    SetConsoleCommand("Stats", "printFPS", &printFPS);
     static void printTickTime()
         { COUT(0) << Game::getInstance().getAvgTickTime() << std::endl; }
-    SetConsoleCommand("printTickTime", &printTickTime);
+    SetConsoleCommand("Stats", "printTickTime", &printTickTime);
 
     std::map<std::string, GameStateInfo> Game::gameStateDeclarations_s;
Index: /code/branches/tutorial/src/libraries/core/GraphicsManager.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/GraphicsManager.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/GraphicsManager.cc	(revision 8051)
@@ -480,16 +480,55 @@
     }
 
+    unsigned int GraphicsManager::getWindowWidth() const
+    {
+        return this->renderWindow_->getWidth();
+    }
+
+    unsigned int GraphicsManager::getWindowHeight() const
+    {
+        return this->renderWindow_->getHeight();
+    }
+
     bool GraphicsManager::hasVSyncEnabled() const
     {
         Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
-        if (options.find("VSync") != options.end())
-            return (options["VSync"].currentValue == "Yes");
+        Ogre::ConfigOptionMap::iterator it = options.find("VSync");
+        if (it != options.end())
+            return (it->second.currentValue == "Yes");
         else
             return false;
     }
 
+    std::string GraphicsManager::getFSAAMode() const
+    {
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("FSAA");
+        if (it != options.end())
+            return it->second.currentValue;
+        else
+            return "";
+    }
+
     std::string GraphicsManager::setScreenResolution(unsigned int width, unsigned int height, bool fullscreen)
     {
-        this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width) + " x " + multi_cast<std::string>(height) + " @ " + multi_cast<std::string>(this->getRenderWindow()->getColourDepth()) + "-bit colour");
+        // workaround to detect if the colour depth should be written to the config file
+        bool bWriteColourDepth = false;
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("Video Mode");
+        if (it != options.end())
+            bWriteColourDepth = (it->second.currentValue.find('@') != std::string::npos);
+
+        if (bWriteColourDepth)
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height)
+                                                                    + " @ " + multi_cast<std::string>(this->getRenderWindow()->getColourDepth()) + "-bit colour");
+        }
+        else
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height));
+        }
+
         this->ogreRoot_->getRenderSystem()->setConfigOption("Full Screen", fullscreen ? "Yes" : "No");
 
Index: /code/branches/tutorial/src/libraries/core/GraphicsManager.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/GraphicsManager.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/GraphicsManager.h	(revision 8051)
@@ -54,4 +54,5 @@
 #include "OrxonoxClass.h"
 
+// tolua_begin
 namespace orxonox
 {
@@ -60,6 +61,8 @@
         Graphics engine manager class
     */
-    class _CoreExport GraphicsManager : public Singleton<GraphicsManager>, public OrxonoxClass, public Ogre::LogListener
-    {
+    class _CoreExport GraphicsManager
+// tolua_end
+        : public Singleton<GraphicsManager>, public OrxonoxClass, public Ogre::LogListener
+    { // tolua_export
         friend class Singleton<GraphicsManager>;
     public:
@@ -74,6 +77,15 @@
         Ogre::RenderWindow* getRenderWindow() { return this->renderWindow_; }
         size_t getRenderWindowHandle();
+
+// tolua_begin
+        static GraphicsManager& getInstance() { return Singleton<GraphicsManager>::getInstance(); } // tolua_export
+
         bool isFullScreen() const;
+        unsigned int getWindowWidth() const;
+        unsigned int getWindowHeight() const;
+
         bool hasVSyncEnabled() const;
+        std::string getFSAAMode() const;
+// tolua_end
 
         void upgradeToGraphics();
@@ -127,6 +139,8 @@
 
         static GraphicsManager* singletonPtr_s;        //!< Pointer to the Singleton
+// tolua_begin
     };
 }
+// tolua_end
 
 #endif /* _GraphicsManager_H__ */
Index: /code/branches/tutorial/src/libraries/core/command/CommandEvaluation.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/CommandEvaluation.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/CommandEvaluation.h	(revision 8051)
@@ -70,9 +70,9 @@
 
         @remarks execCommand_ and hintCommand_ can be different in this case: There are multiple
-        commands avaliable, let's say "tcl", "tclexecute", and "tclquery". The user enters
-        "tcl", which is already a valid command. Now execCommand_ points to the "tcl"-command,
-        but hintCommand_ still points to the autocompletion command of CommandExecutor, because
-        the auto-completion list must still return the three possible commands, "tcl tclexecute tclquery"
-        because the user may want to execute "tclquery" and needs auto-completion.
+        commands avaliable, let's say "tcl" and "TclThreadManager". The user enters "tcl", which
+        is already a valid command. Now execCommand_ points to the "tcl"-command, but hintCommand_
+        still points to the autocompletion command of CommandExecutor, because the auto-completion
+        list must still return the two possible commands, "tcl TclThreadManager" because the user
+        may want to write "TclThreadManager ..." and needs auto-completion.
 
         @see See @ref CommandExecutorExample "this description" for an example.
Index: /code/branches/tutorial/src/libraries/core/command/ConsoleCommandCompilation.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 8051)
@@ -46,11 +46,11 @@
 namespace orxonox
 {
-    SetConsoleCommand("source", source).argumentCompleter(0, autocompletion::files());
+//    SetConsoleCommand("source", source).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
     SetConsoleCommand("echo", echo);
-    SetConsoleCommand("puts", puts);
-
-    SetConsoleCommand("read", read).argumentCompleter(0, autocompletion::files());
-    SetConsoleCommand("append", append).argumentCompleter(0, autocompletion::files());
-    SetConsoleCommand("write", write).argumentCompleter(0, autocompletion::files());
+//    SetConsoleCommand("puts", puts);                                                    // disabled because we use the implementation in Tcl
+
+//    SetConsoleCommand("read", read).argumentCompleter(0, autocompletion::files());      // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("append", append).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("write", write).argumentCompleter(0, autocompletion::files());    // disabled because we use the implementation in Tcl
 
     SetConsoleCommand("calculate", calculate);
Index: /code/branches/tutorial/src/libraries/core/command/Shell.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/Shell.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/Shell.cc	(revision 8051)
@@ -46,8 +46,8 @@
 {
     SetConsoleCommand("log",     OutputHandler::log    );
-    SetConsoleCommand("error",   OutputHandler::error  );
-    SetConsoleCommand("warning", OutputHandler::warning);
-    SetConsoleCommand("info",    OutputHandler::info   );
-    SetConsoleCommand("debug",   OutputHandler::debug  );
+    SetConsoleCommand("error",   OutputHandler::error  ).hide();
+    SetConsoleCommand("warning", OutputHandler::warning).hide();
+    SetConsoleCommand("info",    OutputHandler::info   ).hide();
+    SetConsoleCommand("debug",   OutputHandler::debug  ).hide();
 
     unsigned int Shell::cacheSize_s;
Index: /code/branches/tutorial/src/libraries/core/command/TclBind.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/TclBind.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/TclBind.cc	(revision 8051)
@@ -45,5 +45,5 @@
 {
     SetConsoleCommand("tcl", &TclBind::tcl);
-    SetConsoleCommand("bgerror", &TclBind::bgerror);
+    SetConsoleCommand("bgerror", &TclBind::bgerror).hide();
 
     TclBind* TclBind::singletonPtr_s = 0;
@@ -91,13 +91,14 @@
 
             this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
+            this->interpreter_->def("::orxonox::execute", TclBind::tcl_execute, Tcl::variadic());
             this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
-            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
             this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
 
             try
             {
-                this->interpreter_->eval("proc query        {args}    { ::orxonox::query $args }");
+                this->interpreter_->def("query", TclBind::tcl_query, Tcl::variadic());
+                this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
                 this->interpreter_->eval("proc crossquery   {id args} { ::orxonox::crossquery 0 $id $args }");
-                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossquery 0 $id $args }");
+                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossexecute 0 $id $args }");
                 this->interpreter_->eval("proc running      {}        { return 1 }");
                 this->interpreter_->eval("set id 0");
@@ -154,10 +155,33 @@
     {
         COUT(4) << "Tcl_query: " << args.get() << std::endl;
-
+        return TclBind::tcl_helper(args, true);
+    }
+
+    /**
+        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor.
+    */
+    void TclBind::tcl_execute(Tcl::object const &args)
+    {
+        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
+        TclBind::tcl_helper(args, false);
+    }
+
+    /**
+        @brief Helper function, used by tcl_query() and tcl_execute().
+    */
+    std::string TclBind::tcl_helper(Tcl::object const &args, bool bQuery)
+    {
         const std::string& command = stripEnclosingBraces(args.get());
 
         int error;
+        std::string result;
+
         CommandEvaluation evaluation = CommandExecutor::evaluate(command);
-        const std::string& result = evaluation.query(&error);
+
+        if (bQuery)
+            result = evaluation.query(&error).getString();
+        else
+            error = evaluation.execute();
+
         switch (error)
         {
@@ -175,18 +199,4 @@
 
     /**
-        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor.
-    */
-    void TclBind::tcl_execute(Tcl::object const &args)
-    {
-        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
-        const std::string& command = stripEnclosingBraces(args.get());
-
-        if (CommandExecutor::execute(command, false))
-        {
-            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
-        }
-    }
-
-    /**
         @brief Console command, executes Tcl code. Can be used to bind Tcl-commands to a key, because native
         Tcl-commands can not be evaluated and are thus not supported by the key-binder.
@@ -198,13 +208,8 @@
             try
             {
-                const std::string& output = TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
-                if (!output.empty())
-                {
-                    COUT(0) << "tcl> " << output << std::endl;
-                }
-                return output;
+                return TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
             }
             catch (Tcl::tcl_error const &e)
-            {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
+            {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
         }
 
Index: /code/branches/tutorial/src/libraries/core/command/TclBind.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/TclBind.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/TclBind.h	(revision 8051)
@@ -126,4 +126,6 @@
             TclBind(const TclBind& other);      ///< Copy-constructor, not implemented
 
+            static std::string tcl_helper(Tcl::object const &args, bool bQuery);
+
             Tcl::interpreter* interpreter_;     ///< The wrapped Tcl interpreter
             std::string tclDataPath_;           ///< The path to the directory that contains the Orxonox-specific Tcl-files
Index: /code/branches/tutorial/src/libraries/core/command/TclThreadManager.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/command/TclThreadManager.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/command/TclThreadManager.cc	(revision 8051)
@@ -55,6 +55,4 @@
     const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
 
-    SetConsoleCommand("tclexecute", &TclThreadManager::execute).argumentCompleter(0, autocompletion::tclthreads());
-    SetConsoleCommand("tclquery",   &TclThreadManager::query  ).argumentCompleter(0, autocompletion::tclthreads());
     SetConsoleCommand("TclThreadManager", "create",  &TclThreadManager::create);
     SetConsoleCommand("TclThreadManager", "destroy", &TclThreadManager::destroy).argumentCompleter(0, autocompletion::tclthreads());
Index: /code/branches/tutorial/src/libraries/core/input/InputManager.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/input/InputManager.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/input/InputManager.cc	(revision 8051)
@@ -641,3 +641,19 @@
         state->destroy();
     }
+
+    bool InputManager::setMouseExclusive(const std::string& name, TriBool::Value value)
+    {
+        if (name == "empty")
+        {
+            COUT(2) << "InputManager: Changing the empty state is not allowed!" << std::endl;
+            return false;
+        }
+        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
+        if (it != statesByName_.end())
+        {
+            it->second->setMouseExclusive(value);
+            return true;
+        }
+        return false;
+    }
 }
Index: /code/branches/tutorial/src/libraries/core/input/InputManager.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/input/InputManager.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/input/InputManager.h	(revision 8051)
@@ -163,4 +163,11 @@
         */
         bool destroyState(const std::string& name); // tolua_export
+        /**
+        @brief
+            Changes the mouse mode of an input state.
+        @return
+            True if the call was successful, fals if the name was not found
+        */
+        bool setMouseExclusive(const std::string& name, TriBool::Value value); // tolua_export
 
         //-------------------------------
Index: /code/branches/tutorial/src/libraries/core/input/Keyboard.cc
===================================================================
--- /code/branches/tutorial/src/libraries/core/input/Keyboard.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/input/Keyboard.cc	(revision 8051)
@@ -36,16 +36,26 @@
     {
         // update modifiers
-        if (arg.key == OIS::KC_RMENU    || arg.key == OIS::KC_LMENU)
-            modifiers_ |= KeyboardModifier::Alt;   // alt key
-        if (arg.key == OIS::KC_RCONTROL || arg.key == OIS::KC_LCONTROL)
-            modifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
-        if (arg.key == OIS::KC_RSHIFT   || arg.key == OIS::KC_LSHIFT)
-            modifiers_ |= KeyboardModifier::Shift; // shift key
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ |= KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ |= KeyboardModifier::Shift; // shift key
+                break;
+            case OIS::KC_TAB:
+                // Do not distribute the alt+tab event (messes with the operating system)
+                if ((modifiers_ & KeyboardModifier::Alt) != 0)
+                    return true;
+            default:;
+        }
 
-        // Do not distribute the alt+tab event (messes with the operating system)
-        if ((modifiers_ & KeyboardModifier::Alt) != 0 && arg.key == OIS::KC_TAB)
-            return true;
-
-        KeyEvent evt(arg);
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
         super::buttonPressed(evt);
         return true;
@@ -56,14 +66,46 @@
     {
         // update modifiers
-        if (arg.key == OIS::KC_RMENU    || arg.key == OIS::KC_LMENU)
-            modifiers_ &= ~KeyboardModifier::Alt;   // alt key
-        if (arg.key == OIS::KC_RCONTROL || arg.key == OIS::KC_LCONTROL)
-            modifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
-        if (arg.key == OIS::KC_RSHIFT   || arg.key == OIS::KC_LSHIFT)
-            modifiers_ &= ~KeyboardModifier::Shift; // shift key
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ &= ~KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ &= ~KeyboardModifier::Shift; // shift key
+                break;
+            default:;
+        }
 
-        KeyEvent evt(arg);
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
         super::buttonReleased(evt);
         return true;
     }
+
+    /// A map which returns the corresponding chars for some key codes
+    unsigned int Keyboard::getKeyText(const OIS::KeyEvent& arg)
+    {
+        switch (arg.key)
+        {
+            case OIS::KC_NUMPAD0:     return static_cast<unsigned int>('0');
+            case OIS::KC_NUMPAD1:     return static_cast<unsigned int>('1');
+            case OIS::KC_NUMPAD2:     return static_cast<unsigned int>('2');
+            case OIS::KC_NUMPAD3:     return static_cast<unsigned int>('3');
+            case OIS::KC_NUMPAD4:     return static_cast<unsigned int>('4');
+            case OIS::KC_NUMPAD5:     return static_cast<unsigned int>('5');
+            case OIS::KC_NUMPAD6:     return static_cast<unsigned int>('6');
+            case OIS::KC_NUMPAD7:     return static_cast<unsigned int>('7');
+            case OIS::KC_NUMPAD8:     return static_cast<unsigned int>('8');
+            case OIS::KC_NUMPAD9:     return static_cast<unsigned int>('9');
+            case OIS::KC_DECIMAL:     return static_cast<unsigned int>('.');
+            case OIS::KC_DIVIDE:      return static_cast<unsigned int>('/');
+            case OIS::KC_NUMPADENTER: return static_cast<unsigned int>('\n');
+            default:                  return arg.text;
+        }
+    }
 }
Index: /code/branches/tutorial/src/libraries/core/input/Keyboard.h
===================================================================
--- /code/branches/tutorial/src/libraries/core/input/Keyboard.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/core/input/Keyboard.h	(revision 8051)
@@ -83,4 +83,6 @@
         static std::string getClassNameImpl() { return "Keyboard"; }
 
+        static unsigned int getKeyText(const OIS::KeyEvent& arg);
+
         //! Bit mask representing keyboard modifiers
         int modifiers_;
Index: /code/branches/tutorial/src/libraries/network/Host.cc
===================================================================
--- /code/branches/tutorial/src/libraries/network/Host.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/network/Host.cc	(revision 8051)
@@ -38,8 +38,9 @@
 namespace orxonox {
 
+  static const std::string __CC_printRTT_group = "Stats";
   static const std::string __CC_printRTT_name = "printRTT";
 
   SetConsoleCommand("chat", &Host::Chat);
-  SetConsoleCommand(__CC_printRTT_name, &Host::printRTT);
+  SetConsoleCommand(__CC_printRTT_group, __CC_printRTT_name, &Host::printRTT);
 
   // Host*               Host::instance_=0;
@@ -55,5 +56,5 @@
   //   assert(instance_==0);
     instances_s.push_back(this);
-    ModifyConsoleCommand(__CC_printRTT_name).setObject(this);
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(this);
     this->bIsActive_ = false;
   }
@@ -67,5 +68,5 @@
     assert( std::find( instances_s.begin(), instances_s.end(), this )!=instances_s.end() );
     instances_s.erase(std::find( instances_s.begin(), instances_s.end(), this ));
-    ModifyConsoleCommand(__CC_printRTT_name).setObject(0);
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(0);
   }
 
Index: /code/branches/tutorial/src/libraries/tools/Shader.h
===================================================================
--- /code/branches/tutorial/src/libraries/tools/Shader.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/tools/Shader.h	(revision 8051)
@@ -38,4 +38,5 @@
 #include <OgreCompositorInstance.h>
 
+#include "util/MultiType.h"
 #include "util/OgreForwardRefs.h"
 #include "core/ViewportEventListener.h"
Index: /code/branches/tutorial/src/libraries/tools/Timer.cc
===================================================================
--- /code/branches/tutorial/src/libraries/tools/Timer.cc	(revision 8050)
+++ /code/branches/tutorial/src/libraries/tools/Timer.cc	(revision 8051)
@@ -35,4 +35,6 @@
 
 #include <set>
+
+#include <boost/bimap.hpp>
 
 #include "util/Clock.h"
@@ -41,25 +43,54 @@
 #include "core/command/CommandExecutor.h"
 #include "core/command/Functor.h"
+#include "tools/interfaces/TimeFactorListener.h"
 
 namespace orxonox
 {
     SetConsoleCommand("delay", &delay).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("delayreal", &delayreal).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("killdelay", &killdelay);
     SetConsoleCommand("killdelays", &killdelays);
 
-    static std::set<Timer*> delaytimerset;
-
-    /**
-        @brief Console-command: Calls another console command after @a delay seconds.
+    static boost::bimap<unsigned int, Timer*> delaytimers;
+    static unsigned int delayHandleCounter = 0;
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (game time).
         @param delay The delay in seconds
         @param command The console command
-    */
-    void delay(float delay, const std::string& command)
-    {
-        Timer* delaytimer = new Timer();
-        delaytimerset.insert(delaytimer);
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delay(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new Timer(), delay, command);
+    }
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (real time)
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delayreal(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new RealTimer(), delay, command);
+    }
+
+    /**
+        @brief Helper function, used by delay() and delayreal() to add a delayed command.
+        @param timer The timer which will execute the command
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command)
+    {
+        delaytimers.insert(boost::bimap<unsigned int, Timer*>::value_type(++delayHandleCounter, timer));
 
         const ExecutorStaticPtr& delayexecutor = createExecutor(createFunctor(&executeDelayedCommand));
-        delayexecutor->setDefaultValues(delaytimer, command);
-        delaytimer->setTimer(delay, false, delayexecutor);
+        delayexecutor->setDefaultValues(timer, command);
+        timer->setTimer(delay, false, delayexecutor);
+
+        return delayHandleCounter;
     }
 
@@ -73,5 +104,5 @@
         CommandExecutor::execute(command);
         timer->destroy();
-        delaytimerset.erase(timer);
+        delaytimers.right.erase(timer);
     }
 
@@ -81,8 +112,21 @@
     void killdelays()
     {
-        for (std::set<Timer*>::iterator it = delaytimerset.begin(); it != delaytimerset.end(); ++it)
-            (*it)->destroy();
-
-        delaytimerset.clear();
+        for (boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.begin(); it != delaytimers.left.end(); ++it)
+            it->second->destroy();
+
+        delaytimers.clear();
+    }
+
+    /**
+        @brief Console-command: Kills a delayed command with given handle.
+    */
+    void killdelay(unsigned int handle)
+    {
+        boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.find(handle);
+        if (it != delaytimers.left.end())
+        {
+            it->second->destroy();
+            delaytimers.left.erase(it);
+        }
     }
 
@@ -93,5 +137,5 @@
     {
         this->init();
-        RegisterObject(Timer);
+        RegisterRootObject(Timer);
     }
 
@@ -106,5 +150,5 @@
     {
         this->init();
-        RegisterObject(Timer);
+        RegisterRootObject(Timer);
 
         this->setTimer(interval, bLoop, executor, bKillAfterCall);
@@ -123,4 +167,12 @@
 
         this->time_ = 0;
+    }
+
+    /**
+        @brief Returns the current time factor of the game.
+    */
+    float Timer::getTimeFactor()
+    {
+        return TimeFactorListener::getTimeFactor();
     }
 
@@ -168,3 +220,24 @@
         }
     }
+
+    ///////////////
+    // RealTimer //
+    ///////////////
+    /// @copydoc Timer::Timer
+    RealTimer::RealTimer()
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// @copydoc Timer::Timer(float, bool, const ExecutorPtr&, bool)
+    RealTimer::RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall) : Timer(interval, bLoop, executor, bKillAfterCall)
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// Returns always 1 because RealTimer doesn't depend on the game time.
+    float RealTimer::getTimeFactor()
+    {
+        return 1;
+    }
 }
Index: /code/branches/tutorial/src/libraries/tools/Timer.h
===================================================================
--- /code/branches/tutorial/src/libraries/tools/Timer.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/tools/Timer.h	(revision 8051)
@@ -81,18 +81,26 @@
 #include "core/OrxonoxClass.h"
 #include "core/command/Executor.h"
-#include "tools/interfaces/TimeFactorListener.h"
 
 namespace orxonox
 {
-    void delay(float delay, const std::string& command);
-    void killdelays();
+    unsigned int delay(float delay, const std::string& command);
+    unsigned int delayreal(float delay, const std::string& command);
+
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command);
     void executeDelayedCommand(Timer* timer, const std::string& command);
 
+    void killdelay(unsigned int handle);
+    void killdelays();
+
     /**
-        @brief Timer is a helper class that executes a function after a given amount of time.
+        @brief Timer is a helper class that executes a function after a given amount of seconds in game-time.
 
         @see See @ref TimerExample "Timer.h" for an example.
+
+        The time interval of Timer depends on the game time, hence it stops if the game is paused or runs
+        slower/faster if the game-speed is modified. See RealTimer for a timer class which doesn't depend
+        on the game time.
     */
-    class _ToolsExport Timer : public TimeFactorListener
+    class _ToolsExport Timer : virtual public OrxonoxClass
     {
         public:
@@ -123,26 +131,26 @@
             void run();
 
-            /// Re-starts the Timer: The executor will be called after @a interval seconds.
+            /// Re-starts the timer: The executor will be called after @a interval seconds.
             inline void startTimer()
                 { this->bActive_ = true; this->time_ = this->interval_; }
-            /// Stops the Timer.
+            /// Stops the timer.
             inline void stopTimer()
                 { this->bActive_ = false; this->time_ = this->interval_; }
-            /// Pauses the Timer - it will continue with the actual state if you call unpauseTimer().
+            /// Pauses the timer - it will continue with the actual state if you call unpauseTimer().
             inline void pauseTimer()
                 { this->bActive_ = false; }
-            /// Unpauses the Timer - continues with the given state.
+            /// Unpauses the timer - continues with the given state.
             inline void unpauseTimer()
                 { this->bActive_ = true; }
-            /// Returns true if the Timer is active (neither stopped nor paused).
+            /// Returns true if the timer is active (neither stopped nor paused).
             inline bool isActive() const
                 { return this->bActive_; }
-            /// Returns the remaining time until the Timer calls the executor.
+            /// Returns the remaining time until the timer calls the executor.
             inline float getRemainingTime() const
                 { return static_cast<float>(this->time_ / 1000000.0f); }
-            /// Increases the remaining time of the Timer by the given amount of time (in seconds).
+            /// Increases the remaining time of the timer by the given amount of time (in seconds).
             inline void addTime(float time)
                 { if (time > 0.0f) this->time_ += static_cast<long long>(time * 1000000.0f); }
-            /// Decreases the remaining time of the Timer by the given amount of time (in seconds)
+            /// Decreases the remaining time of the timer by the given amount of time (in seconds)
             inline void removeTime(float time)
                 { if (time > 0.0f) this->time_ -= static_cast<long long>(time * 1000000.0f); }
@@ -156,4 +164,7 @@
             void tick(const Clock& time);
 
+        protected:
+            virtual float getTimeFactor();
+
         private:
             void init();
@@ -163,9 +174,25 @@
             long long interval_;    //!< The time-interval in micro seconds
             bool bLoop_;            //!< If true, the executor gets called every @a interval seconds
-            bool bActive_;          //!< If true, the Timer ticks and calls the executor if the time's up
+            bool bActive_;          //!< If true, the timer ticks and calls the executor if the time's up
             bool bKillAfterCall_;   //!< If true the timer gets deleted after it expired and called the executor
 
             long long time_;        //!< Internal variable, counting the time untill the next executor-call
     };
+
+    /**
+        @brief RealTimer is a helper class that executes a function after a given amount of seconds in real-time.
+
+        The time interval of RealTimer doesn't depend on the game time, it will also call the function
+        if the game is paused. See Timer for a timer class that depends on the game time.
+    */
+    class _ToolsExport RealTimer : public Timer
+    {
+        public:
+            RealTimer();
+            RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall = false);
+
+        protected:
+            virtual float getTimeFactor();
+    };
 }
 
Index: /code/branches/tutorial/src/libraries/tools/ToolsPrereqs.h
===================================================================
--- /code/branches/tutorial/src/libraries/tools/ToolsPrereqs.h	(revision 8050)
+++ /code/branches/tutorial/src/libraries/tools/ToolsPrereqs.h	(revision 8051)
@@ -85,4 +85,5 @@
     class Mesh;
     class ParticleInterface;
+    class RealTimer;
     class ResourceCollection;
     class ResourceLocation;
Index: /code/branches/tutorial/src/orxonox/ChatInputHandler.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/ChatInputHandler.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/ChatInputHandler.cc	(revision 8051)
@@ -28,15 +28,24 @@
 
 #include "ChatInputHandler.h"
+
+#include <cassert>
+#include <string>
+#include <CEGUIWindow.h>
+#include <CEGUIWindowManager.h>
+#include <elements/CEGUIListbox.h>
+#include <elements/CEGUIListboxItem.h>
+#include <elements/CEGUIListboxTextItem.h>
+
 #include "util/ScopedSingletonManager.h"
 #include "core/CoreIncludes.h"
 #include "core/GUIManager.h"
-#include "core/CorePrereqs.h"
 #include "core/command/ConsoleCommand.h"
-#include <CEGUIWindow.h>
-#include <elements/CEGUIListbox.h>
-#include <elements/CEGUIListboxItem.h>
-#include <elements/CEGUIListboxTextItem.h>
-#include <CEGUIWindowManager.h>
-#include <string>
+#include "core/input/InputBuffer.h"
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+#include "network/Host.h"
+
+#include "PlayerManager.h"
+#include "infos/PlayerInfo.h"
 
 namespace orxonox
Index: /code/branches/tutorial/src/orxonox/ChatInputHandler.h
===================================================================
--- /code/branches/tutorial/src/orxonox/ChatInputHandler.h	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/ChatInputHandler.h	(revision 8051)
@@ -30,28 +30,12 @@
 #define _ChatInputHandler_H__
 
-/* std includes */
-#include <deque>
+#include <OrxonoxPrereqs.h>
+
 #include <string>
-#include <fstream>
-#include <iostream>
-#include <cassert>
 #include <CEGUIForwardRefs.h>
 #include <CEGUIcolour.h>
 
-/* project includes */
-#include <OrxonoxPrereqs.h>
-#include <core/BaseObject.h>
-#include <core/PathConfig.h>
-
-#include "core/input/InputBuffer.h"
-#include "core/input/InputManager.h"
-#include "core/input/InputState.h"
-
-#include <network/ChatListener.h>
-#include <PlayerManager.h>
-#include <infos/PlayerInfo.h>
-
-#include "../libraries/network/Host.h"
-#include <util/Singleton.h>
+#include "util/Singleton.h"
+#include "network/ChatListener.h"
 
 namespace orxonox // tolua_export
Index: /code/branches/tutorial/src/orxonox/LevelInfo.h
===================================================================
--- /code/branches/tutorial/src/orxonox/LevelInfo.h	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/LevelInfo.h	(revision 8051)
@@ -109,5 +109,5 @@
             @return Returns the XML-filename (including *.oxw extension) of the Level.
             */
-            inline const std::string& getXMLFilename(void) { return this->xmlfilename_; } // tolua_export
+            inline const std::string& getXMLFilename(void) const { return this->xmlfilename_; } // tolua_export
 
         protected:
@@ -212,5 +212,9 @@
     {
         bool operator() (const LevelInfoItem* lhs, const LevelInfoItem* rhs) const
-            { return getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) < 0; }
+            {
+                if(getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) == 0)
+                    return getLowercase(lhs->getXMLFilename()).compare(getLowercase(rhs->getXMLFilename())) < 0;
+                return getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) < 0;
+            }
     };
     
Index: /code/branches/tutorial/src/orxonox/LevelManager.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/LevelManager.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/LevelManager.cc	(revision 8051)
@@ -251,4 +251,5 @@
         // Iterate over all the found *.oxw files
         COUT(3) << "Loading LevelInfos..." << std::endl;
+        std::set<std::string> names;
         for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
         {
@@ -277,8 +278,12 @@
                 }
 
+                // Warn about levels with the same name.
+                if(!names.insert(info->getName()).second)
+                    COUT(2) << "Warning: Multiple levels (" << info->getXMLFilename() << ") with name '" << info->getName() << "' found!" << std::endl;
+
                 // Warn about multiple items so that it gets fixed quickly
                 if(availableLevels_.find(info) != availableLevels_.end())
                 {
-                    COUT(2) << "Warning: Multiple levels with name '" << info->getName() << "' found!" << std::endl;
+                    COUT(2) << "Warning: Multiple levels (" << info->getXMLFilename() << ") with same name '" << info->getName() << "' and filename found! Exluding..." << std::endl;
                     // Delete LevelInfoItem to avoid a dangling pointer
                     delete info;
Index: /code/branches/tutorial/src/orxonox/LevelManager.h
===================================================================
--- /code/branches/tutorial/src/orxonox/LevelManager.h	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/LevelManager.h	(revision 8051)
@@ -112,5 +112,5 @@
             // Helpers to allow fast access to the availableLevels list.
             unsigned int nextIndex_; //! The next expected index to be accessed.
-            std::set<LevelInfoItem*, LevelInfoCompare>::iterator nextLevel_; //! The nex expected Level to be accessed.
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator nextLevel_; //! The next expected Level to be accessed.
 
             // config values
Index: /code/branches/tutorial/src/orxonox/gamestates/GSLevel.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/gamestates/GSLevel.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/gamestates/GSLevel.cc	(revision 8051)
@@ -46,4 +46,5 @@
 #include "LevelManager.h"
 #include "PlayerManager.h"
+#include "GSRoot.h"
 
 namespace orxonox
@@ -156,7 +157,9 @@
         COUT(0) << "Loading level..." << std::endl;
         startFile_ = new XMLFile(LevelManager::getInstance().getDefaultLevel());
-        Loader::open(startFile_);
+        bool loaded = Loader::open(startFile_);
 
         Core::getInstance().updateLastLevelTimestamp();
+        if(!loaded)
+            GSRoot::delayedStartMainMenu();
     }
 
Index: /code/branches/tutorial/src/orxonox/gamestates/GSMainMenu.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/gamestates/GSMainMenu.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/gamestates/GSMainMenu.cc	(revision 8051)
@@ -68,5 +68,5 @@
         RegisterRootObject(GSMainMenu);
 
-        InputManager::getInstance().createInputState("MainMenuHackery", true, true)->setKeyHandler(KeyBinderManager::getInstance().getDefaultAsHandler());
+        InputManager::getInstance().createInputState("MainMenuHackery")->setKeyHandler(KeyBinderManager::getInstance().getDefaultAsHandler());
 
         // create an empty Scene
Index: /code/branches/tutorial/src/orxonox/gamestates/GSRoot.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/gamestates/GSRoot.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/gamestates/GSRoot.cc	(revision 8051)
@@ -38,4 +38,6 @@
 #include "tools/interfaces/Tickable.h"
 
+#include "GSLevel.h"
+
 namespace orxonox
 {
@@ -45,4 +47,6 @@
     static const std::string __CC_setPause_name = "setPause";
     static const std::string __CC_pause_name = "pause";
+
+    /*static*/ bool GSRoot::startMainMenu_s = false;
 
     SetConsoleCommand("printObjects", &GSRoot::printObjects).hide();
@@ -98,4 +102,10 @@
     void GSRoot::update(const Clock& time)
     {
+        if(startMainMenu_s)
+        {
+            delayedStartMainMenu();
+            startMainMenu_s = false;
+        }
+
         for (ObjectList<Timer>::iterator it = ObjectList<Timer>::begin(); it; )
         {
@@ -175,3 +185,12 @@
             callStaticNetworkFunction(&TimeFactorListener::setTimeFactor, CLIENTID_UNKNOWN, factor_new);
     }
+
+    /*static*/ void GSRoot::delayedStartMainMenu(void)
+    {
+        if(!startMainMenu_s)
+            startMainMenu_s = true;
+        else
+            GSLevel::startMainMenu();
+    }
+
 }
Index: /code/branches/tutorial/src/orxonox/gamestates/GSRoot.h
===================================================================
--- /code/branches/tutorial/src/orxonox/gamestates/GSRoot.h	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/gamestates/GSRoot.h	(revision 8051)
@@ -54,4 +54,6 @@
         void pause();
 
+        static void delayedStartMainMenu(void);
+
     protected:
         virtual void changedTimeFactor(float factor_new, float factor_old);
@@ -60,4 +62,5 @@
         bool                  bPaused_;
         float                 timeFactorPauseBackup_;
+        static bool           startMainMenu_s;
     };
 }
Index: /code/branches/tutorial/src/orxonox/gametypes/Gametype.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/gametypes/Gametype.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/gametypes/Gametype.cc	(revision 8051)
@@ -30,4 +30,5 @@
 
 #include "util/Math.h"
+#include "core/Core.h"
 #include "core/CoreIncludes.h"
 #include "core/ConfigValueIncludes.h"
@@ -386,5 +387,9 @@
                     if (allplayersready && hashumanplayers)
                     {
-                        this->gtinfo_->startCountdown_ = this->initialStartCountdown_;
+                        // If in developer's mode, there is no start countdown.
+                        if(Core::getInstance().inDevMode())
+                            this->gtinfo_->startCountdown_ = 0;
+                        else
+                            this->gtinfo_->startCountdown_ = this->initialStartCountdown_;
                         this->gtinfo_->bStartCountdownRunning_ = true;
                     }
Index: /code/branches/tutorial/src/orxonox/graphics/Model.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/graphics/Model.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/graphics/Model.cc	(revision 8051)
@@ -60,5 +60,5 @@
     void Model::setConfigValues()
     {
-        SetConfigValueExternal(bGlobalEnableLod_, "GraphicsSettings", "enableModelLoD", true)
+        SetConfigValueExternal(bGlobalEnableLod_, "GraphicsSettings", "enableMeshLoD", true)
             .description("Enable level of detail for models");
     }
Index: /code/branches/tutorial/src/orxonox/overlays/InGameConsole.cc
===================================================================
--- /code/branches/tutorial/src/orxonox/overlays/InGameConsole.cc	(revision 8050)
+++ /code/branches/tutorial/src/orxonox/overlays/InGameConsole.cc	(revision 8051)
@@ -49,5 +49,4 @@
 #include "core/ConfigValueIncludes.h"
 #include "core/command/ConsoleCommand.h"
-#include "core/GUIManager.h"
 #include "core/input/InputManager.h"
 #include "core/input/InputState.h"
@@ -60,6 +59,6 @@
     const float CHAR_WIDTH = 7.45f; // fix this please - determine the char-width dynamically
 
-    SetConsoleCommand("InGameConsole", "openConsole", &InGameConsole::openConsole).addShortcut();
-    SetConsoleCommand("InGameConsole", "closeConsole", &InGameConsole::closeConsole).addShortcut();
+    SetConsoleCommand("InGameConsole", "openConsole", &InGameConsole::openConsole);
+    SetConsoleCommand("InGameConsole", "closeConsole", &InGameConsole::closeConsole);
 
     ManageScopedSingleton(InGameConsole, ScopeID::Graphics, false);
@@ -534,5 +533,4 @@
         {
             this->bActive_ = false;
-            GUIManager::getInstance().getLuaState()->doString("inGameConsoleClosed()"); // Notify the SheetManager in lua, that the console has been closed.
             InputManager::getInstance().leaveState("console");
             this->shell_->unregisterListener(this);
@@ -611,5 +609,4 @@
     /*static*/ void InGameConsole::closeConsole()
     {
-        GUIManager::getInstance().getLuaState()->doString("inGameConsoleClosed()");  // Notify the SheetManager in lua, that the console has been closed, but not by ESC.
         InGameConsole::getInstance().deactivate();
     }
