Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/data/gui/scripts/SheetManager.lua @ 7970

Last change on this file since 7970 was 7928, checked in by landauf, 14 years ago

more improvements for keyboard control of menus:

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