Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

implemented new keyboard control of menu buttons with these new features:

  • more intuitive placement of buttons in table (row/column format instead of linear index)
  • no need to overwrite onShow() and onKeyPressed() functions, no need for P.buttonList
  • highlights the selected button in a different layout than mouse hovering
  • remembers the selection while moving through the menu hierarchy, but resets it if the menu is closed
  • allows preselected button (for example "Yes" in decision popup)
  • when opening a menu, the first selected button is not always the upper left, but instead depends on the pressed key (e.g. the 'up' key selects the button at the bottom, while the 'down' key selects the button at the top. once a button is selected, the keys behave as usual)

+ fixed wrong callback function in ingame menu

  • Property svn:eol-style set to native
File size: 7.8 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    if bHidePrevious then
124        for i = 1, activeMenuSheets.size - 1 do
125            activeMenuSheets[i].sheet:hide()
126        end
127    end
128
129    menuSheet:show()
130    menuSheetsRoot:activate()
131
132    return menuSheet
133end
134
135function hideMenuSheet(name)
136    local sheetTuple = activeMenuSheets[name]
137    if sheetTuple == nil then
138        return
139    end
140
141    -- Hide the sheet
142    sheetTuple.sheet:hide()
143
144    -- Show sheets that were hidden by the sheet to be removed
145    local i = activeMenuSheets.size
146    -- Only do something if all sheets on top of sheetTuple
147    -- have bHidePrevious == true and sheetTuple.bHidePrevious == true
148    while i > 0 do
149        if activeMenuSheets[i].bHidePrevious then
150            if activeMenuSheets[i] == sheetTuple then
151                i = i - 1
152                while i > 0 do
153                    activeMenuSheets[i].sheet:show()
154                    if activeMenuSheets[i].bHidePrevious then
155                        break
156                    end
157                    i = i - 1
158                end
159            end
160            break
161        end
162        i = i - 1
163    end
164
165    -- Remove sheet with its tuple from the table
166    menuSheetsRoot:removeChildWindow(sheetTuple.sheet.window)
167    table.remove(activeMenuSheets, table.findIndex(activeMenuSheets, sheetTuple))
168    activeMenuSheets[name] = nil
169    activeMenuSheets.size = activeMenuSheets.size - 1
170    activeMenuSheets.topSheetTuple = activeMenuSheets[activeMenuSheets.size]
171
172    -- If sheet is the MainMenu
173    if name == "MainMenu" then
174        mainMenuLoaded = false
175    end
176
177    -- Leave the input state
178    if not sheetTuple.bNoInput then
179        inputMgr:leaveState(sheetTuple.sheet.inputState)
180    end
181
182    -- CURSOR SHOWING
183    local i = activeMenuSheets.size
184    -- Find top most sheet that doesn't have tShowCusor == TriBool.Dontcare
185    while i > 0 and activeMenuSheets[i].sheet.tShowCursor == TriBool.Dontcare do
186        i = i - 1
187    end
188    if i > 0 and activeMenuSheets[i].sheet.tShowCursor == TriBool.True then
189        showCursor()
190    else
191        hideCursor()
192    end
193
194    -- Count the number of sheets that don't need input till the first that does.
195    local counter = noInputSheetIndex()
196    -- Resume control if the last (non-noInput) menu is hidden
197    if counter == 0 then
198        orxonox.HumanController:resumeControl()
199        hideCursor()
200    end
201
202    sheetTuple.sheet:afterHide()
203end
204
205-- Hides all menu GUI sheets
206function hideAllMenuSheets()
207    while activeMenuSheets.size ~= 0 do
208        hideMenuSheet(activeMenuSheets.topSheetTuple.sheet.name)
209    end
210end
211
212function keyESC()
213    -- HUGE, very HUGE hacks!
214
215    -- If the InGameConsole is active, ignore the ESC command.
216    if bInGameConsoleClosed == true then
217        bInGameConsoleClosed = false
218        return
219    end
220
221    -- Count the number of sheets that don't need input till the first that does.
222    local counter = noInputSheetIndex()
223
224    -- If the first sheet that needs input is the MainMenu.
225    if noInputSheetCounter() == 1 and activeMenuSheets[counter].sheet.name == "MainMenu" then
226        orxonox.execute("exit")
227    -- If there is at least one sheet that needs input.
228    elseif counter > 0 then
229        orxonox.execute("hideGUI "..activeMenuSheets[counter].sheet.name)
230    else
231        showMenuSheet("InGameMenu")
232    end
233end
234
235function keyPressed(e)
236    local we = tolua.cast(e, "CEGUI::KeyEventArgs")
237    local sheet = activeMenuSheets[activeMenuSheets.size]
238    code = tostring(we.scancode)
239    -- Some preprocessing
240    if not mainMenuLoaded and not sheet.bNoInput then
241        if code == "1" then
242            keyESC()
243        elseif code == "0"then
244            orxonox.CommandExecutor:execute("openConsole")
245        end
246    end
247    sheet.sheet:keyPressed()
248end
249
250function setBackgroundImage(imageSet, imageName)
251    guiMgr:setBackgroundImage(imageSet, imageName)
252end
253
254function noInputSheetIndex()
255    -- Count the number of sheets that don't need input till the first that does.
256    local index = activeMenuSheets.size
257    while index > 0 and activeMenuSheets[index].bNoInput do
258        index = index - 1
259    end
260    return index
261end
262
263function noInputSheetCounter()
264    -- Count the number of sheets that do need input.
265    local counter = activeMenuSheets.size
266    for i = 1,activeMenuSheets.size do
267        if activeMenuSheets[i].bNoInput then
268            counter = counter - 1
269        end
270    end
271    return counter
272end
273
274function inGameConsoleClosed()
275    bInGameConsoleClosed = not bInGameConsoleClosed;
276end
277
278----------------------
279--- Initialisation ---
280----------------------
281
282hideCursor()
Note: See TracBrowser for help on using the repository browser.