Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/data/gui/scripts/SheetManager.lua @ 8079

Last change on this file since 8079 was 8079, checked in by landauf, 13 years ago

merged usability branch back to trunk

incomplete summary of the changes in this branch:

  • enhanced keyboard navigation in GUIs
  • implemented new graphics menu and changeable window size at runtime
  • added developer mode
  • HUD shows if game is paused, game pauses if ingame menu is opened
  • removed a few obsolete commands and hid some that are more for internal use
  • numpad works in console and gui
  • faster loading of level info
  • enhanced usage of compositors (Shader class)
  • improved camera handling, configurable FOV and aspect ratio
  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1-- SheetManager.lua
2
3local cursor = CEGUI.MouseCursor:getSingleton()
4local loadedSheets = {}
5local activeMenuSheets = {size = 0, topSheetTuple = nil}
6local menuSheetsRoot = guiMgr:getMenuRootWindow()
7local bInGameConsoleClosed = false
8local mainMenuLoaded = false
9orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "KeyDown", "keyPressed")
10orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "Sized", "windowResized")
11
12------------------------
13--- Global functions ---
14------------------------
15
16function hideCursor()
17    if cursor:isVisible() then
18        cursor:hide()
19    end
20end
21
22function showCursor()
23    if not cursor:isVisible() and inputMgr:isMouseExclusive() then
24        cursor:show()
25    end
26end
27
28-- Loads the GUI with the specified name
29-- The name corresponds to the filename of the *.lua and *.layout files
30-- but without the extension
31function loadSheet(name)
32    -- Check if it has already been loaded
33    local sheet = loadedSheets[name]
34    if sheet == nil then
35        -- Load the sheet
36        sheet = require(name)
37        sheet:load()
38        loadedSheets[name] = sheet
39    end
40    return sheet
41end
42
43-- ?
44function showMenuSheet(name, bHidePrevious, bNoInput, ptr)
45    local sheet = showMenuSheet(name, bHidePrevious, bNoInput)
46    sheet.overlay = ptr
47    return sheet
48end
49
50-- Shows the specified menu sheet and loads it if neccessary
51function showMenuSheet(name, bHidePrevious, bNoInput)
52    if name == "" then
53        return nil
54    end
55    -- Get sheet (or load it)
56    local menuSheet = loadSheet(name)
57
58    -- Use sheet's value if nil was provided
59    if bHidePrevious == nil then
60        bHidePrevious = menuSheet.bHidePrevious
61        assert(bHidePrevious ~= nil)
62    end
63
64    -- Set bNoInput to false if it hasn't been set.
65    if bNoInput == nil then
66        bNoInput = false
67    end
68
69    -- Count the number of sheets that don't need input till the first that does.
70    local counter = noInputSheetIndex()
71    -- Pause game control if this is the first menu to be displayed
72    -- HUGE HACK?
73    if bNoInput == false and counter == 0 then
74        orxonox.HumanController:pauseControl()
75    end
76
77    -- Hide if already displayed (to make sure it is up front in the end)
78    if activeMenuSheets[name] ~= nil then
79        hideMenuSheet(name)
80    end
81
82    if bNoInput == true then
83        menuSheet.tShowCursor = TriBool.Dontcare
84    end
85
86    -- Add the sheet in a tuple of additional information
87    local sheetTuple =
88    {
89        ["sheet"]          = menuSheet,
90        ["bHidePrevious"]  = bHidePrevious,
91        ["bNoInput"]       = bNoInput,
92        ["name"]           = name
93    }
94    table.insert(activeMenuSheets, sheetTuple) -- indexed array access
95    activeMenuSheets[name] = sheetTuple -- name access
96    activeMenuSheets.size = activeMenuSheets.size + 1
97    activeMenuSheets.topSheetTuple = sheetTuple
98
99    -- Add sheet to the root window
100    menuSheetsRoot:addChildWindow(menuSheet.window)
101
102    -- If sheet is the MainMenu
103    if name == "MainMenu" then
104        mainMenuLoaded = true
105    end
106
107    -- Handle input distribution
108    if bNoInput == false then
109        inputMgr:enterState(menuSheet.inputState)
110    end
111
112    -- Only change cursor situation if menuSheet.tShowCursor ~= TriBool.Dontcare
113    if menuSheet.tShowCursor == TriBool.True then
114        showCursor()
115    elseif menuSheet.tShowCursor == TriBool.False then
116        hideCursor()
117    end
118
119    -- Hide all previous sheets if necessary
120    local previous
121    if bHidePrevious then
122        for i = 1, activeMenuSheets.size - 1 do
123            previous = activeMenuSheets[i].sheet
124            previous:hide()
125        end
126    end
127
128    menuSheet:show()
129    menuSheetsRoot:activate()
130
131    -- select first button if the menu was opened with the keyboard
132    if previous and previous.pressedEnter and menuSheet:hasSelection() == false then
133        menuSheet:setSelectionNear(1, 1)
134    end
135
136    return menuSheet
137end
138
139function hideMenuSheet(name)
140    local sheetTuple = activeMenuSheets[name]
141    if sheetTuple == nil then
142        return
143    end
144
145    -- Hide the sheet
146    sheetTuple.sheet:hide()
147
148    -- Show sheets that were hidden by the sheet to be removed
149    local i = activeMenuSheets.size
150    -- Only do something if all sheets on top of sheetTuple
151    -- have bHidePrevious == true and sheetTuple.bHidePrevious == true
152    while i > 0 do
153        if activeMenuSheets[i].bHidePrevious then
154            if activeMenuSheets[i] == sheetTuple then
155                i = i - 1
156                while i > 0 do
157                    activeMenuSheets[i].sheet:show()
158                    if activeMenuSheets[i].bHidePrevious then
159                        break
160                    end
161                    i = i - 1
162                end
163            end
164            break
165        end
166        i = i - 1
167    end
168
169    -- Remove sheet with its tuple from the table
170    menuSheetsRoot:removeChildWindow(sheetTuple.sheet.window)
171    table.remove(activeMenuSheets, table.findIndex(activeMenuSheets, sheetTuple))
172    activeMenuSheets[name] = nil
173    activeMenuSheets.size = activeMenuSheets.size - 1
174    activeMenuSheets.topSheetTuple = activeMenuSheets[activeMenuSheets.size]
175
176    -- If sheet is the MainMenu
177    if name == "MainMenu" then
178        mainMenuLoaded = false
179    end
180
181    -- Leave the input state
182    if not sheetTuple.bNoInput then
183        inputMgr:leaveState(sheetTuple.sheet.inputState)
184    end
185
186    -- CURSOR SHOWING
187    local i = activeMenuSheets.size
188    -- Find top most sheet that doesn't have tShowCusor == TriBool.Dontcare
189    while i > 0 and activeMenuSheets[i].sheet.tShowCursor == TriBool.Dontcare do
190        i = i - 1
191    end
192    if i > 0 and activeMenuSheets[i].sheet.tShowCursor == TriBool.True then
193        showCursor()
194    else
195        hideCursor()
196    end
197
198    -- Count the number of sheets that don't need input till the first that does.
199    local counter = noInputSheetIndex()
200    -- Resume control if the last (non-noInput) menu is hidden
201    if counter == 0 then
202        orxonox.HumanController:resumeControl()
203        hideCursor()
204    end
205
206    sheetTuple.sheet:quit()
207end
208
209-- Hides all menu GUI sheets
210function hideAllMenuSheets()
211    while activeMenuSheets.size ~= 0 do
212        hideMenuSheet(activeMenuSheets.topSheetTuple.sheet.name)
213    end
214end
215
216function keyESC()
217    -- HUGE, very HUGE hacks!
218
219    -- If the InGameConsole is active, ignore the ESC command.
220    if bInGameConsoleClosed == true then
221        bInGameConsoleClosed = false
222        return
223    end
224
225    -- Count the number of sheets that don't need input till the first that does.
226    local counter = noInputSheetIndex()
227
228    -- If the first sheet that needs input is the MainMenu.
229    if noInputSheetCounter() == 1 and activeMenuSheets[counter].sheet.name == "MainMenu" then
230        orxonox.execute("exit")
231    -- If there is at least one sheet that needs input.
232    elseif counter > 0 then
233        orxonox.execute("hideGUI "..activeMenuSheets[counter].sheet.name)
234    else
235        showMenuSheet("InGameMenu")
236    end
237end
238
239function keyPressed(e)
240    local we = tolua.cast(e, "CEGUI::KeyEventArgs")
241    local sheet = activeMenuSheets[activeMenuSheets.size]
242    code = tostring(we.scancode)
243    -- Some preprocessing
244    if not mainMenuLoaded and not sheet.bNoInput then
245        if code == "1" then
246            keyESC()
247        elseif code == "0"then
248            orxonox.CommandExecutor:execute("InGameConsole openConsole")
249        end
250    end
251    sheet.sheet:keyPressed()
252end
253
254function windowResized(e)
255    for name, sheet in pairs(loadedSheets) do
256        if orxonox.GraphicsManager:getInstance():isFullScreen() or sheet.tShowCursor == TriBool.False then
257            inputMgr:setMouseExclusive(sheet.inputState, TriBool.True)
258        else
259            inputMgr:setMouseExclusive(sheet.inputState, TriBool.False)
260        end
261    end
262    local sheetTuple = activeMenuSheets[activeMenuSheets.size]
263    if sheetTuple then
264        if orxonox.GraphicsManager:getInstance():isFullScreen() and sheetTuple.sheet.tShowCursor ~= TriBool.False then
265            showCursor()
266        else
267            hideCursor()
268        end
269        sheetTuple.sheet:windowResized()
270    end
271end
272
273function setBackgroundImage(imageSet, imageName)
274    guiMgr:setBackgroundImage(imageSet, imageName)
275end
276
277function noInputSheetIndex()
278    -- Count the number of sheets that don't need input till the first that does.
279    local index = activeMenuSheets.size
280    while index > 0 and activeMenuSheets[index].bNoInput do
281        index = index - 1
282    end
283    return index
284end
285
286function noInputSheetCounter()
287    -- Count the number of sheets that do need input.
288    local counter = activeMenuSheets.size
289    for i = 1,activeMenuSheets.size do
290        if activeMenuSheets[i].bNoInput then
291            counter = counter - 1
292        end
293    end
294    return counter
295end
296
297function inGameConsoleClosed()
298    bInGameConsoleClosed = not bInGameConsoleClosed;
299end
300
301function getGUIFirstActive(name, bHidePrevious, bNoInput)
302    local sheet = activeMenuSheets.topSheetTuple
303    -- If the topmost gui sheet has the input name
304    if sheet ~= nil and sheet.name == name then
305        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, false);
306    else
307        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, true);
308    end
309end
310
311----------------------
312--- Initialisation ---
313----------------------
314
315hideCursor()
Note: See TracBrowser for help on using the repository browser.