· 8 years ago · Jun 24, 2018, 03:58 AM
1 --*****************************************************************************
2--* File: lua/modules/ui/uiutil.lua
3--* Author: Chris Blackwell
4--* Summary: Various utility functions to make UI scripts easier and more consistent
5--*
6--* Copyright © 2005 Gas Powered Games, Inc. All rights reserved.
7--*****************************************************************************
8
9local LazyVar = import('/lua/system/lazyvar.lua')
10local LayoutHelpers = import('/lua/maui/layouthelpers.lua')
11local Group = import('/lua/maui/group.lua').Group
12local Text = import('/lua/maui/text.lua').Text
13local MultiLineText = import('/lua/maui/multilinetext.lua').MultiLineText
14local Button = import('/lua/maui/button.lua').Button
15local Edit = import('/lua/maui/edit.lua').Edit
16local Checkbox = import('/lua/maui/Checkbox.lua').Checkbox
17local Scrollbar = import('/lua/maui/scrollbar.lua').Scrollbar
18local Bitmap = import('/lua/maui/bitmap.lua').Bitmap
19local Cursor = import('/lua/maui/cursor.lua').Cursor
20local Prefs = import('/lua/user/prefs.lua')
21local Border = import('/lua/maui/border.lua').Border
22local ItemList = import('/lua/maui/itemlist.lua').ItemList
23local Layouts = import('/lua/ui/skins/layouts.lua')
24
25----FIX: this variable should be reviewed - it was being referenced below without being innitialized - so not entirely sure what it should be set to, or where
26---- this is a temp fix to allow MP testing to proceed - bfricks 1/7/09
27local takeFocus = false
28
29local EffectHelpers= nil
30local CursorHiddenRefCount= 0
31--* Handy global variables to assist skinning
32buttonFont = import('/lua/system/lazyvar.lua').Create() -- default font used for button faces
33factionFont = import('/lua/system/lazyvar.lua').Create() -- default font used for dialog button faces
34dialogButtonFont = import('/lua/system/lazyvar.lua').Create() -- default font used for dialog button faces
35bodyFont = import('/lua/system/lazyvar.lua').Create() -- font used for all other text
36fixedFont = import('/lua/system/lazyvar.lua').Create() -- font used for fixed width characters
37titleFont = import('/lua/system/lazyvar.lua').Create() -- font used for titles and labels
38fontColor = import('/lua/system/lazyvar.lua').Create() -- common font color
39fontOverColor = import('/lua/system/lazyvar.lua').Create() -- common font color
40fontDownColor = import('/lua/system/lazyvar.lua').Create() -- common font color
41tooltipTitleColor = import('/lua/system/lazyvar.lua').Create() -- common font color
42tooltipBorderColor = import('/lua/system/lazyvar.lua').Create() -- common font color
43bodyColor = import('/lua/system/lazyvar.lua').Create() -- common color for dialog body text
44dialogCaptionColor = import('/lua/system/lazyvar.lua').Create() -- common color for dialog titles
45dialogColumnColor = import('/lua/system/lazyvar.lua').Create() -- common color for column headers in a dialog
46dialogButtonColor = import('/lua/system/lazyvar.lua').Create() -- common color for buttons in a dialog
47highlightColor = import('/lua/system/lazyvar.lua').Create() -- text highlight color
48disabledColor = import('/lua/system/lazyvar.lua').Create() -- text disabled color
49panelColor = import('/lua/system/lazyvar.lua').Create() -- default color when drawing a panel
50transparentPanelColor = import('/lua/system/lazyvar.lua').Create() -- default color when drawing a transparent panel
51consoleBGColor = import('/lua/system/lazyvar.lua').Create() -- console background color
52consoleFGColor = import('/lua/system/lazyvar.lua').Create() -- console foreground color (text)
53consoleTextBGColor = import('/lua/system/lazyvar.lua').Create() -- console text background color
54menuFontSize = import('/lua/system/lazyvar.lua').Create() -- font size used on main in game escape menu
55CurrentControls= {}
56local CurrentResolution = nil -- '480' or '720'. Use nil for autoselect based on xbox resolution setting
57-- Central place for all fonts, sizes, etc for the game. Add more as we need them.
58local AllFontsX360 =
59{
60 ['480'] =
61 {
62 General = { size= 14, fontName= titleFont },
63 Title = { size= 30, fontName= titleFont },
64 MenuButtonText= { size= 14, fontName= titleFont }, -- Example "Single Player"
65 MenuTitleText= { size= 14, fontName= titleFont }, -- Example "Main Menu"
66 MenuProfileText= { size= 14, fontName= titleFont }, -- Example "shaelive"
67 ScreenTitleText= { size= 18, fontName= titleFont }, -- Example "Skirmish Setup"
68 ComboBoxText= { size= 12, fontName= titleFont, overColor = 'FFFFFFFF', color = 'FFA0A0A0', disabledColor = 'FF707070' },
69 StandardButtonText= { size= 12, fontName= titleFont }, -- Example "OK", "Cancel" on bottom panel
70 DescriptionText= { size= 12, fontName= bodyFont }, -- Any long descriptions: briefing text, etc.
71 CampaignBriefingText= { size= 12 }, -- uses faction color & font
72 CampaignDifficultyText= { size= 14, fontName= titleFont }, -- "Difficulty"
73 CampaignFactionNameText= { size= 18, fontName= titleFont },
74 CampaignChooseFactionText= { size= 14, fontName= titleFont }, -- Example "Skirmish Setup"
75 CampaignUEFFont= { fontName= titleFont, color= 'FF709090' },
76 CampaignCybranFont= { fontName= titleFont, color= 'orange' },
77 CampaignAeonFont= { fontName= titleFont, color= 'FF55FF00' },
78 CampaignMissionSelectText= { size= 14 }, -- uses faction color & font
79 FileListHeadingText= { size= 16, fontName= titleFont }, -- Name, Date
80 FileListElementText= { size= 14, fontName= bodyFont, color= fontColor, highlightColor= 'ffffffa0' }, -- Bob's UEF Game
81 OptionDescriptionText= { size= 13, fontName= titleFont },
82 LobbyHeaderText= { size= 14, fontName= titleFont },
83 LobbyMapInfoText = { size= 12, fontName= titleFont },
84 LobbyMapDescriptionText = { size= 10, fontName= titleFont },
85 LobbySettingsCol1Text = { size= 12, fontName= titleFont, color= 'FF709090' },
86 LobbySettingsCol2Text = { size= 12, fontName= titleFont },
87 DialogBoxText = { size= 18, fontName= titleFont },
88 EconomyIncome = { size= 12, fontName= bodyFont, color= 'FF50F050' },
89 EconomyExpense = { size= 12, fontName= bodyFont, color= 'FFF05050' },
90 EconomyWarning = { size= 12, fontName= titleFont },
91 EconomyRate = { size= 18, fontName= bodyFont },
92 EconomyStorage = { size= 14, fontName= bodyFont, color= 'FFD0D0D0' },
93 SubTitlesText = { size= 12, fontName= bodyFont },
94 ContextualHelp = { size= 12, fontName= bodyFont },
95 ScoreHUDText = { size= 12, fontName= bodyFont },
96 TalkingHeadTitleText = { size= 16, fontName= bodyFont },
97 TalkingHeadText = { size= 12, fontName= bodyFont },
98 ConstructionWheelText = { size= 12, fontName= bodyFont },
99 DebriefScoreLabelText = { size= 12, fontName= bodyFont },
100 DebriefScoreValueText = { size= 14, fontName= bodyFont },
101 DebriefScoreHeadingText = { size= 14, fontName= bodyFont },
102 DebriefReportText = { size= 14, fontName= bodyFont },
103 DebriefReportHeadingText = { size= 18, fontName= bodyFont },
104 SkirmishScoreValueText = { size= 13, fontName= bodyFont },
105 SkirmishGamerTagText = { size= 16, fontName= bodyFont },
106 ToolTipTitleText = { size= 14, fontName= titleFont, color= 'black', bgColor= 'FF93ADAD' },
107 ToolTipText = { size= 12, fontName= titleFont },
108 UnitViewText = { size= 12, fontName= bodyFont },
109 ConnectivityTitleText = { size= 16, fontName= bodyFont },
110 ConnectivityText = { size= 14, fontName= bodyFont },
111 ConnectDialogs= { size= 14, fontName=bodyFont}, -- Any disconnect dialogs
112 ObjectiveDescriptionText = { size= 14, fontName= bodyFont },
113 ObjectiveShortDescriptionText = { size= 14, fontName= bodyFont },
114 ObjectiveTimeText = { size= 12, fontName= bodyFont },
115 ObjectiveTypeText = { size= 18, fontName= bodyFont },
116 RankingsColumnTitleText = { size= 14, fontName= bodyFont },
117 RankingsRowText = { size= 14, fontName= bodyFont },
118 ResourceText = { green= 'FF50F050', red= 'FFF05050' },
119 },
120 ['720'] =
121 {
122 General = { size= 14, fontName= titleFont },
123 Title = { size= 30, fontName= titleFont },
124 MenuButtonText= { size= 22, fontName= titleFont },
125 MenuTitleText= { size= 24, fontName= titleFont },
126 MenuProfileText= { size= 24, fontName= bodyFont }, -- Example "shaelive"
127 ScreenTitleText= { size= 26, fontName= titleFont },
128 ComboBoxText= { size= 18, fontName= titleFont, overColor = 'FFFFFFFF', color = 'FFFFFFFF', disabledColor = 'FF404040' },
129 StandardButtonText= { size= 20, fontName= titleFont }, -- Example "OK", "Cancel" on bottom panel
130 DescriptionText= { size= 18, fontName= bodyFont }, -- Any long descriptions: briefing text, etc.
131 CampaignBriefingText= { size= 20 },
132 CampaignDifficultyText= { size= 18, fontName= titleFont }, -- "Difficulty"
133 CampaignFactionNameText= { size= 24, fontName= titleFont },
134 CampaignChooseFactionText= { size= 20, fontName= titleFont }, -- Example "Skirmish Setup"
135 CampaignUEFFont= { fontName= titleFont, color= 'FF709090' },
136 CampaignCybranFont= { fontName= titleFont, color= 'orange' },
137 CampaignAeonFont= { fontName= titleFont, color= 'FF55FF00' },
138 CampaignMissionSelectText= { size= 20 }, -- uses faction color & font
139 FileListHeadingText= { size= 18, fontName= titleFont }, -- Name, Date
140 FileListElementText= { size= 16, fontName= bodyFont, color= fontColor, highlightColor= 'ffffffa0' }, -- Bob's UEF Game
141 OptionDescriptionText= { size= 18, fontName= titleFont },
142 LobbyHeaderText= { size= 18, fontName= titleFont },
143 LobbyMapInfoText = { size= 16, fontName= titleFont },
144 LobbyMapDescriptionText = { size= 18, fontName= titleFont },
145 LobbySettingsCol1Text = { size= 18, fontName= titleFont, color= 'FF709090' },
146 LobbySettingsCol2Text = { size= 18, fontName= titleFont },
147 DialogBoxText = { size= 18, fontName= titleFont },
148 EconomyIncome = { size= 20, fontName= bodyFont, color= 'FF50F050' },
149 EconomyExpense = { size= 20, fontName= bodyFont, color= 'FFF05050' },
150 EconomyWarning = { size= 16, fontName= titleFont },
151 EconomyRate = { size= 25, fontName= bodyFont },
152 EconomyStorage = { size= 20, fontName= bodyFont, color= 'FFD0D0D0' },
153 SubTitlesText = { size= 22, fontName=bodyFont },
154 ContextualHelp = { size= 12, fontName= bodyFont },
155 ScoreHUDText = { size= 14, fontName= bodyFont },
156 TalkingHeadTitleText = { size= 20, fontName= bodyFont },
157 TalkingHeadText = { size= 18, fontName= bodyFont },
158 ConstructionWheelText = { size= 18, fontName= bodyFont },
159 DebriefScoreLabelText = { size= 16, fontName= bodyFont },
160 DebriefScoreValueText = { size= 16, fontName= bodyFont },
161 DebriefScoreHeadingText = { size= 18, fontName= bodyFont },
162 DebriefReportText = { size= 18, fontName= bodyFont },
163 DebriefReportHeadingText = { size= 20, fontName= bodyFont },
164 SkirmishScoreValueText = { size= 18, fontName= bodyFont },
165 SkirmishGamerTagText = { size= 20, fontName= bodyFont },
166 ToolTipTitleText = { size= 18, fontName= titleFont, color= 'black', bgColor= 'FF93ADAD' },
167 ToolTipText = { size= 16, fontName= titleFont },
168 UnitViewText = { size= 18, fontName= bodyFont },
169 ConnectivityTitleText = { size= 18, fontName= bodyFont },
170 ConnectivityText = { size= 16, fontName= bodyFont },
171 ConnectDialogs= { size= 20, fontName=bodyFont}, -- Any disconnect dialogs
172 ObjectiveDescriptionText = { size= 18, fontName= bodyFont },
173 ObjectiveShortDescriptionText = { size= 18, fontName= bodyFont },
174 ObjectiveShortDescriptionScoreText = { size= 16, fontName= bodyFont },
175 ObjectiveTimeText = { size= 16, fontName= bodyFont },
176 ObjectiveTypeText = { size= 22, fontName= bodyFont },
177 RankingsColumnTitleText = { size= 20, fontName= bodyFont },
178 RankingsRowText = { size= 18, fontName= bodyFont },
179 ResourceText = { green= 'FF50F050', red= 'FFF05050' },
180 },
181}
182DefaultControls = {
183 Forward = 'A',
184 ComboActivate = 'A',
185 LeftRightComboActivate = 'Y',
186}
187
188Fonts = nil
189if (IsXbox()) then
190 Fonts = AllFontsX360[CurrentResolution or GetXboxScreenHeight()]
191end
192
193-- table of layouts supported by this skin, not a lazy var as we don't need updates
194layouts = nil
195
196--* other handy variables!
197consoleDepth = false -- in order to get the console to always be on top, assign this number and never go over
198local CurrentControlStack= {}
199local CurrentStackRefCount= 0
200networkBool = import('/lua/system/lazyvar.lua').Create() -- boolean whether the game is local or networked
201
202-- Default scenario for skirmishes / MP Lobby
203defaultScenario = '/maps/scmp_039/scmp_039_scenario.lua'
204
205--* These values MUST NOT CHANGE! They syncronize with values in UIManager.h and are used to
206--* specify a render pass
207-- render before the world is rendered
208UIRP_UnderWorld = 1
209-- reserved for world views
210UIRP_World = 2
211-- render with glow (note, won't render when world isn't visible)
212UIRP_Glow = 4
213-- render without glow
214UIRP_PostGlow = 8
215
216--* useful key codes, weirdly inconsistent, some are MSW vk codes, some are wxW codes :(
217VK_BACKSPACE = 8
218VK_TAB = 9
219VK_ENTER = 13
220VK_ESCAPE = 27
221VK_SPACE = 32
222VK_PRIOR = 33
223VK_NEXT = 34
224VK_UP = 38
225VK_DOWN = 40
226VK_F1 = 112
227VK_F2 = 113
228VK_F3 = 114
229VK_F4 = 115
230VK_F5 = 116
231VK_F6 = 117
232VK_F7 = 118
233VK_F8 = 119
234VK_F9 = 120
235VK_F10 = 121
236VK_F11 = 122
237VK_F12 = 123
238VK_PAUSE = 310
239
240local currentSkin = import('/lua/system/lazyvar.lua').Create()
241
242currentLayout = false
243changeLayoutFunction = false -- set this function to get called with the new layout name when layout changes
244
245function HideCursor()
246 CursorHiddenRefCount= CursorHiddenRefCount + 1
247 GetCursor():HideJoystickCursor()
248end
249
250function ShowCursor()
251 CursorHiddenRefCount= CursorHiddenRefCount - 1
252 if CursorHiddenRefCount <= 0 then
253 GetCursor():ShowJoystickCursor()
254 CursorHiddenRefCount= 0
255 end
256end
257--* layout control, sets current layout preference
258function SetCurrentLayout(layout)
259 if not layout then return end
260 -- make sure this skin contains the layout, otherwise do nothing
261 local foundLayout = false
262 for index, complayout in layouts do
263 if layout == complayout then
264 foundLayout = true
265 break
266 end
267 end
268 if not foundLayout then return end
269
270 currentLayout = layout
271 Prefs.SetToCurrentProfile("layout", currentLayout)
272 --TEMP - this is here because the grids get hosed when you switch layouts. The grids will be fixed
273 -- but until then this will have to suffice
274 SelectUnits(nil)
275 if changeLayoutFunction then changeLayoutFunction(layout) end
276end
277
278function GetNetworkBool()
279 local sessionClientsTable = GetSessionClients()
280 local networkBool = false
281 local sessionBool = true
282 if sessionClientsTable != nil then
283 networkBool = SessionIsMultiplayer()
284 else
285 sessionBool = false
286 end
287 return networkBool, sessionBool
288end
289
290function GetAnimationPrefs()
291 return true
292end
293
294function GetLayoutFilename(key)
295 if Layouts[currentLayout][key] then
296 return Layouts[currentLayout][key]
297 else
298 WARN('No layout file for \'', key, '\' in the current layout. Expect layout errors.')
299 return false
300 end
301end
302
303--* skin control, sets the current skin table
304function SetCurrentSkin(skin)
305 local skins = import('/lua/ui/skins/skins.lua').skins
306
307 if skins[skin] == nil then
308 skin = 'uef'
309 end
310
311 currentSkin:Set(skin)
312
313 tooltipTitleColor:Set(skins[skin].tooltipTitleColor or skins['default'].tooltipTitleColor)
314 tooltipBorderColor:Set(skins[skin].tooltipBorderColor or skins['default'].tooltipBorderColor)
315 buttonFont:Set(skins[skin].buttonFont or skins['default'].buttonFont)
316 factionFont:Set(skins[skin].factionFont or skins['default'].factionFont)
317 dialogButtonFont:Set(skins[skin].dialogButtonFont or skins['default'].dialogButtonFont)
318 bodyFont:Set(skins[skin].bodyFont or skins['default'].bodyFont)
319 fixedFont:Set(skins[skin].fixedFont or skins['default'].fixedFont)
320 titleFont:Set(skins[skin].titleFont or skins['default'].titleFont)
321 fontColor:Set(skins[skin].fontColor or skins['default'].fontColor)
322 bodyColor:Set(skins[skin].bodyColor or skins['default'].bodyColor)
323 fontOverColor:Set(skins[skin].fontOverColor or skins['default'].fontOverColor)
324 fontDownColor:Set(skins[skin].fontDownColor or skins['default'].fontDownColor)
325 dialogCaptionColor:Set(skins[skin].dialogCaptionColor or skins['default'].dialogCaptionColor)
326 dialogColumnColor:Set(skins[skin].dialogColumnColor or skins['default'].dialogColumnColor)
327 dialogButtonColor:Set(skins[skin].dialogButtonColor or skins['default'].dialogButtonColor)
328 highlightColor:Set(skins[skin].highlightColor or skins['default'].highlightColor)
329 disabledColor:Set(skins[skin].disabledColor or skins['default'].disabledColor)
330 panelColor:Set(skins[skin].panelColor or skins['default'].panelColor)
331 transparentPanelColor:Set(skins[skin].transparentPanelColor or skins['default'].transparentPanelColor)
332 consoleBGColor:Set(skins[skin].consoleBGColor or skins['default'].consoleBGColor)
333 consoleFGColor:Set(skins[skin].consoleFGColor or skins['default'].consoleFGColor)
334 consoleTextBGColor:Set(skins[skin].consoleTextBGColor or skins['default'].consoleTextBGColor)
335 menuFontSize:Set(skins[skin].menuFontSize or skins['default'].menuFontSize)
336 layouts = skins[skin].layouts or skins['default'].layouts
337
338 local curLayout = Prefs.GetFromCurrentProfile("layout")
339
340 if not curLayout then
341 SetCurrentLayout(layouts[1])
342 else
343 local validLayout = false
344 for i, layoutName in layouts do
345 if layoutName == curLayout then
346 validLayout = true
347 break
348 end
349 end
350 if validLayout then
351 SetCurrentLayout(curLayout)
352 else
353 SetCurrentLayout(layouts[1])
354 end
355 end
356
357 Prefs.SetToCurrentProfile("skin", skin)
358end
359
360--* cycle through all available skins
361function RotateSkin(direction)
362 if not SessionIsActive() or import('/lua/ui/game/gamemain.lua').IsNISMode() then
363 return
364 end
365
366 local skins = import('/lua/ui/skins/skins.lua').skins
367
368 -- build an array of skin names
369 local skinNames = {}
370 for skin in skins do
371 table.insert(skinNames, skin)
372 end
373
374 local dir
375 if direction == '+' then
376 dir = 1
377 else
378 dir = -1
379 end
380
381 -- Find the next skin from our current skin, skipping default, as it's not really a skin!
382 -- note that if the skin table is updated while running, the order of the table might change
383 -- so your cycle may be different. No big deal, just be aware it's a side effect.
384 local numSkins = table.getn(skinNames)
385 for index, skinName in skinNames do
386 if skinName == currentSkin() then
387 local nextSkinIndex = index + dir
388 if nextSkinIndex > numSkins then nextSkinIndex = 1 end
389 if nextSkinIndex < 1 then nextSkinIndex = numSkins end
390 if skinNames[nextSkinIndex] == 'default' then -- skip default entry as it's not really a skin
391 nextSkinIndex = nextSkinIndex + dir
392 if nextSkinIndex > numSkins then nextSkinIndex = 1 end
393 if nextSkinIndex < 1 then nextSkinIndex = numSkins end
394 end
395 LOG('attempting to set skin to: ', skinNames[nextSkinIndex])
396 SetCurrentSkin(skinNames[nextSkinIndex])
397 break
398 end
399 end
400end
401
402--* cycle through all available layouts
403function RotateLayout(direction)
404
405 -- disable when in Screen Capture mode
406 if import('/lua/ui/game/gamemain.lua').gameUIHidden then
407 return
408 end
409
410 local dir
411 if direction == '+' then
412 dir = 1
413 else
414 dir = -1
415 end
416
417 local numLayouts = table.getn(layouts)
418 for index, layoutName in layouts do
419 if layoutName == currentLayout then
420 local nextLayoutIndex = index + dir
421 if nextLayoutIndex > numLayouts then nextLayoutIndex = 1 end
422 if nextLayoutIndex < 1 then nextLayoutIndex = numLayouts end
423 SetCurrentLayout(layouts[nextLayoutIndex])
424 break
425 end
426 end
427end
428
429--* given a path and name relative to the skin path, returns the full path based on the current skin
430function UIFile(filespec)
431 local skins = import('/lua/ui/skins/skins.lua').skins
432 local visitingSkin = currentSkin()
433 local currentPath = skins[visitingSkin].texturesPath
434
435 if visitingSkin == nil or currentPath == nil then
436 return nil
437 end
438
439 -- if current skin is default, then don't bother trying to look for it, just append the default dir
440 if visitingSkin == 'default' then
441 return currentPath .. filespec
442 else
443 while visitingSkin do
444 local curFile = currentPath .. filespec
445 if DiskGetFileInfo(curFile) then
446 return curFile
447 else
448 visitingSkin = skins[visitingSkin].default
449 if visitingSkin then currentPath = skins[visitingSkin].texturesPath end
450 end
451 end
452 end
453
454 LOG("Warning: Unable to find file ", filespec)
455 -- pass out the final string anyway so resource loader can gracefully fail
456 return filespec
457end
458
459--* return the filename as a lazy var function to allow triggering of OnDirty
460function SkinnableFile(filespec)
461 return function()
462 return UIFile(filespec)
463 end
464end
465
466function GetCurrentXboxScreenHeight()
467 local widescreen
468 if not CurrentResolution then
469 CurrentResolution, widescreen = GetXboxScreenHeight()
470 Fonts= AllFontsX360[CurrentResolution]
471 end
472 return CurrentResolution, widescreen
473end
474
475function GetRightScreenSafeEdge()
476 local res
477 local wideScreen
478 res, wideScreen = GetXboxScreenHeight()
479 if wideScreen then
480 if res == '480' then
481 return 680
482 else
483 return 1200
484 end
485 else
486 if res == '480' then
487 return 600
488 else
489 return 900
490 end
491 end
492end
493
494function GetInGameEdgeOffset(rightEdge)
495 local res
496 local wideScreen
497 res, wideScreen = GetXboxScreenHeight()
498 if wideScreen then
499 wideScreen= 'wide'
500 else
501 wideScreen= 'normal'
502 end
503 if rightEdge then
504 rightEdge= 'Right'
505 else
506 rightEdge= 'Left'
507 end
508 local Offsets=
509 {
510 ['480'] =
511 {
512 wide =
513 {
514 Left= 20, -- Extra screen safe area
515 Right= 200, -- 854 - 15 - 640 ish.
516 },
517 normal =
518 {
519 Left= 0,
520 Right= 0,
521 },
522 },
523 ['720'] =
524 {
525 wide =
526 {
527 Left= 10,
528 Right= 0, -- (1280-960)
529 },
530 normal =
531 {
532 Left= 0,
533 Right= 0,
534 },
535 },
536 }
537
538 return Offsets[res][wideScreen][rightEdge]
539end
540
541local function CheckCurrentResolution()
542 if not CurrentResolution then
543 CurrentResolution = GetXboxScreenHeight()
544 Fonts= AllFontsXbox360[CurrentResolution]
545 end
546end
547
548function UIGetFileForRes(filespec, noskin)
549 local newFilespec= filespec
550-- CheckCurrentResolution()
551-- if CurrentResolution != '480' then
552-- newFilespec = string.gsub(filespec, '480', CurrentResolution)
553-- end
554 if not noskin then
555 return function() return UIFile(newFilespec) end
556 else
557 return UIFile(newFilespec)
558 end
559end
560
561ButtonIcons=
562{
563 { 'A', UIGetFileForRes('/game/buttons480/ButtonA.dds'), },
564 { 'B', UIGetFileForRes('/game/buttons480/ButtonB.dds'), },
565 { 'X', UIGetFileForRes('/game/buttons480/ButtonX.dds'), },
566 { 'Y', UIGetFileForRes('/game/buttons480/ButtonY.dds'), },
567 { 'DPadUp', UIGetFileForRes('/game/buttons480/DPadUp.dds'), },
568 { 'DPadDown', UIGetFileForRes('/game/buttons480/DPadDown.dds'), },
569 { 'DPadLeft', UIGetFileForRes('/game/buttons480/DPadLeft.dds'), },
570 { 'DPadRight',UIGetFileForRes('/game/buttons480/DPadRight.dds'), },
571 { 'Start', UIGetFileForRes('/game/buttons480/ButtonStart.dds'), },
572 { 'Back', UIGetFileForRes('/game/buttons480/ButtonBack.dds'), },
573 { 'LeftShoulder', UIGetFileForRes('/game/buttons480/LeftShoulder.dds'), },
574 { 'RightShoulder',UIGetFileForRes('/game/buttons480/RightShoulder.dds'), },
575 { 'LeftThumb', UIGetFileForRes('/game/buttons480/LeftThumb.dds'), },
576 { 'RightThumb',UIGetFileForRes('/game/buttons480/RightThumb.dds'), },
577 { 'LeftTrigger', UIGetFileForRes('/game/buttons480/LeftTrigger.dds'), },
578 { 'RightTrigger',UIGetFileForRes('/game/buttons480/RightTrigger.dds'), },
579}
580
581--* each UI screen needs something to be responsible for parenting all its controls so
582--* placement and destruction can occur. This creates a group which fills the screen.
583function CreateScreenGroup(root, debugName)
584 if not root then return end
585 local screenGroup = Group(root, debugName or "screenGroup")
586 LayoutHelpers.FillParent(screenGroup, root)
587 return screenGroup
588end
589
590--* Get cursor information for a given cursor ID
591function GetCursor(id)
592 local skins = import('/lua/ui/skins/skins.lua').skins
593 local cursors = skins[currentSkin()].cursors or skins['default'].cursors
594 if not cursors[id] then
595 LOG("Requested cursor not found: " .. id)
596 end
597 return cursors[id][1], cursors[id][2], cursors[id][3], cursors[id][4], cursors[id][5]
598end
599
600--* create the one cursor used by the game
601function CreateCursor()
602 if not UseGamepad() then
603 local cursor = Cursor(true, GetCursor('DEFAULT'))
604 return cursor
605 else
606 local cursor = Cursor(false, GetCursor('DEFAULT_GAMEPAD'))
607 cursor:UseQuadCursor(true)
608 return cursor
609 end
610end
611
612--* return a text object with the appropriate font set
613function CreateText(parent, label, pointSize, font)
614 label = LOC(label) or LOC("<LOC uiutil_0000>[no text]")
615 font = font or buttonFont
616 local text = Text(parent, "Text: " .. label)
617 text:SetFont(font, pointSize)
618 text:SetColor(fontColor)
619 text:SetText(label)
620 return text
621end
622
623function SetupEditStd(control, foreColor, backColor, highlightFore, highlightBack, fontFace, fontSize, charLimit)
624 if charLimit then
625 control:SetMaxChars(charLimit)
626 end
627 if foreColor then
628 control:SetForegroundColor(foreColor)
629 end
630 if backColor then
631 control:SetBackgroundColor(backColor)
632 end
633 if highlightFore then
634 control:SetHighlightForegroundColor(highlightFore)
635 end
636 if highlightBack then
637 control:SetHighlightBackgroundColor(highlightBack)
638 end
639 if fontFace and fontSize then
640 control:SetFont(fontFace, fontSize)
641 end
642
643 control.OnCharPressed = function(self, charcode)
644 if charcode == VK_TAB then
645 return true
646 end
647 local charLim = self:GetMaxChars()
648 if STR_Utf8Len(self:GetText()) >= charLim then
649 local sound = Sound({Cue = 'UI_Menu_Error_01', Bank = 'Interface',})
650 PlaySound(sound)
651 end
652 end
653end
654
655--* return a button set up with a text overlay and a click sound
656function CreateButton(parent, up, down, over, disabled, label, pointSize, textOffsetVert, textOffsetHorz, clickCue, rolloverCue)
657 textOffsetVert = textOffsetVert or 0
658 textOffsetHorz = textOffsetHorz or 0
659 if clickCue == "NO_SOUND" then
660 clickCue = nil
661 else
662 clickCue = clickCue or "UI_Menu_MouseDown_Sml"
663 end
664 if rolloverCue == "NO_SOUND" then
665 rolloverCue = nil
666 else
667 rolloverCue = rolloverCue or "UI_Menu_Rollover_Sml"
668 end
669 if type(up) == 'string' then
670 up = SkinnableFile(up)
671 end
672 if type(down) == 'string' then
673 down = SkinnableFile(down)
674 end
675 if type(over) == 'string' then
676 over = SkinnableFile(over)
677 end
678 if type(disabled) == 'string' then
679 disabled = SkinnableFile(disabled)
680 end
681
682 local button = Button(parent, up, down, over, disabled, clickCue, rolloverCue)
683 button:UseAlphaHitTest(true)
684
685 if label and pointSize then
686 button.label = CreateText(button, label, pointSize)
687 LayoutHelpers.AtCenterIn(button.label, button, textOffsetVert, textOffsetHorz)
688 button.label:DisableHitTest()
689
690 -- if text exists, set up to grey it out
691 button.OnDisable = function(self)
692 Button.OnDisable(self)
693 button.label:SetColor(disabledColor)
694 end
695
696 button.OnEnable = function(self)
697 Button.OnEnable(self)
698 button.label:SetColor(fontColor)
699 end
700 button.OnRolloverEvent = function(self, event)
701 if event == 'enter' then
702 button.label:SetColor(fontOverColor)
703 elseif event == 'exit' then
704 button.label:SetColor(fontColor)
705 elseif event == 'down' then
706 button.label:SetColor(fontDownColor)
707 end
708 end
709 end
710
711 return button
712end
713
714function SetNewButtonTextures(button, up, down, over, disabled)
715 -- if strings passed in, make them skinnables, otherwise assume they are already skinnables
716 if type(up) == 'string' then
717 up = SkinnableFile(up)
718 end
719 if type(down) == 'string' then
720 down = SkinnableFile(down)
721 end
722 if type(over) == 'string' then
723 over = SkinnableFile(over)
724 end
725 if type(disabled) == 'string' then
726 disabled = SkinnableFile(disabled)
727 end
728
729 button:SetNewTextures(up, down, over, disabled)
730end
731
732--* create a button with standardized texture names
733--* given a path and button name prefix, generates the four button asset file names according to the naming convention
734function CreateButtonStd(parent, filename, label, pointSize, textOffsetVert, textOffsetHorz, clickCue, rolloverCue)
735 return CreateButton(parent
736 , filename .. "_btn_up.dds"
737 , filename .. "_btn_down.dds"
738 , filename .. "_btn_over.dds"
739 , filename .. "_btn_dis.dds"
740 , label
741 , pointSize
742 , textOffsetVert
743 , textOffsetHorz
744 , clickCue
745 , rolloverCue
746 )
747end
748
749function CreateCheckbox(parent, up, upsel, over, oversel, dis, dissel, clickCue, rollCue)
750 local clickSound = clickCue or 'UI_Mini_MouseDown'
751 local rollSound = rollCue or 'UI_Mini_Rollover'
752 local checkbox = Checkbox( parent, up, upsel, over, oversel, dis, dissel, clickSound, rollSound)
753 checkbox:UseAlphaHitTest(true)
754 return checkbox
755end
756
757function CreateCheckboxStd(parent, filename, clickCue, rollCue)
758 local checkbox = CreateCheckbox( parent,
759 SkinnableFile(filename .. '-d_btn_up.dds'),
760 SkinnableFile(filename .. '-s_btn_up.dds'),
761 SkinnableFile(filename .. '-d_btn_over.dds'),
762 SkinnableFile(filename .. '-s_btn_over.dds'),
763 SkinnableFile(filename .. '-d_btn_dis.dds'),
764 SkinnableFile(filename .. '-s_btn_dis.dds'),
765 clickCue, rollCue)
766 return checkbox
767end
768
769function CreateDialogButtonStd(parent, filename, label, pointSize, textOffsetVert, textOffsetHorz, clickCue, rolloverCue)
770 local button = CreateButtonStd(parent,filename,label,pointSize,textOffsetVert,textOffsetHorz, clickCue, rolloverCue)
771 button.label:SetFont( dialogButtonFont, pointSize )
772 button.label:SetColor( dialogButtonColor )
773 return button
774end
775
776function SetNewButtonStdTextures(button, filename)
777 SetNewButtonTextures(button
778 , filename .. "_btn_up.dds"
779 , filename .. "_btn_down.dds"
780 , filename .. "_btn_over.dds"
781 , filename .. "_btn_dis.dds")
782end
783
784--* return the standard scrollbar
785function CreateVertScrollbarFor(attachto, offset, filename)
786 offset = offset or 0
787 local textureName = filename or '/small-vert_scroll/'
788 local scrollbg = textureName..'back_scr_mid.dds'
789 local scrollbarmid = textureName..'bar-mid_scr_over.dds'
790 local scrollbartop = textureName..'bar-top_scr_up.dds'
791 local scrollbarbot = textureName..'bar-bot_scr_up.dds'
792 if filename then
793 scrollbg = textureName..'back_scr_mid.dds'
794 scrollbarmid = textureName..'bar-mid_scr_up.dds'
795 scrollbartop = textureName..'bar-top_scr_up.dds'
796 scrollbarbot = textureName..'bar-bot_scr_up.dds'
797 end
798 local scrollbar = Scrollbar(attachto, import('/lua/maui/scrollbar.lua').ScrollAxis.Vert)
799 scrollbar:SetTextures( SkinnableFile(scrollbg)
800 ,SkinnableFile(scrollbarmid)
801 ,SkinnableFile(scrollbartop)
802 ,SkinnableFile(scrollbarbot))
803
804 local scrollUpButton = Button( scrollbar
805 , SkinnableFile(textureName..'arrow-up_scr_up.dds')
806 , SkinnableFile(textureName..'arrow-up_scr_over.dds')
807 , SkinnableFile(textureName..'arrow-up_scr_down.dds')
808 , SkinnableFile(textureName..'arrow-up_scr_dis.dds')
809 , "UI_Arrow_Click")
810
811 local scrollDownButton = Button( scrollbar
812 , SkinnableFile(textureName..'arrow-down_scr_up.dds')
813 , SkinnableFile(textureName..'arrow-down_scr_over.dds')
814 , SkinnableFile(textureName..'arrow-down_scr_down.dds')
815 , SkinnableFile(textureName..'arrow-down_scr_dis.dds')
816 , "UI_Arrow_Click")
817
818 scrollbar.Left:Set(function() return attachto.Right() + offset end)
819 scrollbar.Top:Set(scrollUpButton.Bottom)
820 scrollbar.Bottom:Set(scrollDownButton.Top)
821
822 scrollUpButton.Left:Set(scrollbar.Left)
823 scrollUpButton.Top:Set(attachto.Top)
824 scrollDownButton.Left:Set(scrollbar.Left)
825 scrollDownButton.Bottom:Set(attachto.Bottom)
826
827 scrollbar.Right:Set(scrollUpButton.Right)
828
829 scrollbar:AddButtons(scrollUpButton, scrollDownButton)
830 scrollbar:SetScrollable(attachto)
831
832 return scrollbar
833end
834
835function CreateHorzScrollbarFor(attachto, offset)
836 offset = offset or 0
837 local scrollbar = Scrollbar(attachto, import('/lua/maui/scrollbar.lua').ScrollAxis.Horz)
838 local scrollRightButton = Button( scrollbar
839 , SkinnableFile('/widgets/large-h_scr/arrow-right_scr_up.dds')
840 , SkinnableFile('/widgets/large-h_scr/arrow-right_scr_down.dds')
841 , SkinnableFile('/widgets/large-h_scr/arrow-right_scr_over.dds')
842 , SkinnableFile('/widgets/large-h_scr/arrow-right_scr_dis.dds'))
843 scrollRightButton.Right:Set(attachto.Right)
844 scrollRightButton.Bottom:Set(function() return attachto.Top() + offset end)
845
846 local scrollLeftButton = Button( scrollbar
847 , SkinnableFile('/widgets/large-h_scr/arrow-left_scr_up.dds')
848 , SkinnableFile('/widgets/large-h_scr/arrow-left_scr_down.dds')
849 , SkinnableFile('/widgets/large-h_scr/arrow-left_scr_over.dds')
850 , SkinnableFile('/widgets/large-h_scr/arrow-left_scr_dis.dds'))
851 scrollLeftButton.Left:Set(attachto.Left)
852 scrollLeftButton.Bottom:Set(function() return attachto.Top() + offset end)
853
854 scrollbar:SetTextures( UIFile('/widgets/back_scr/back_scr_mid.dds')
855 ,UIFile('/widgets/large-h_scr/bar-mid_scr_over.dds')
856 ,UIFile('/widgets/large-h_scr/bar-right_scr_over.dds')
857 ,UIFile('/widgets/large-h_scr/bar-left_scr_over.dds'))
858 scrollbar.Left:Set(scrollLeftButton.Right)
859 scrollbar.Right:Set(scrollRightButton.Left)
860 scrollbar.Top:Set(scrollRightButton.Top)
861 scrollbar.Bottom:Set(scrollRightButton.Bottom)
862
863 scrollbar:AddButtons(scrollLeftButton, scrollRightButton)
864 scrollbar:SetScrollable(attachto)
865
866 return scrollbar
867end
868
869-- cause a dialog to get input focus, optional functions to perform when the user hits enter or escape
870-- functions signature is: function()
871function MakeInputModal(control, onEnterFunc, onEscFunc)
872 AddInputCapture(control)
873
874 local oldOnDestroy = control.OnDestroy
875 control.OnDestroy = function(self)
876 RemoveInputCapture(control)
877 oldOnDestroy(self)
878 end
879
880 if onEnterFunc or onEscFunc then
881 control.oldHandleEvent = control.HandleEvent
882 control.HandleEvent = function(self, event)
883 if event.Type == 'KeyDown' then
884 if event.KeyCode == VK_ESCAPE then
885 if onEscFunc then
886 onEscFunc()
887 return true
888 end
889 elseif event.KeyCode == VK_ENTER then
890 if onEnterFunc then
891 onEnterFunc()
892 return true
893 end
894 end
895 end
896 if control.oldHandleEvent then
897 return control.oldHandleEvent(self, event)
898 end
899 return true
900 end
901 end
902end
903
904-- create and manage an info dialog
905-- parent: the control to parent the dialog to
906-- dialogText: the text to display in the dialog
907-- button1Text: text for the first button (opt)
908-- button1Callback: callback function for the first button, signature function() (opt)
909-- button2Text: text for the second button (opt)
910-- button2Callback: callback function for the second button, signature function() (opt)
911-- button3Text: text for the second button (opt)
912-- button3Callback: callback function for the second button, signature function() (opt)
913-- destroyOnCallback: if true, destroy when any button is pressed (if false, you must destroy) (opt)
914-- modalInfo: Sets up modal info for dialog using a table in the form:
915-- escapeButton = int 1-3 : the button function to mimic when the escape button is pressed
916-- enterButton = int 1-3 : the button function to mimic when the enterButton is pressed
917-- worldCover = bool : control if a world cover should be shown
918function QuickDialog(parent, dialogText, button1Text, button1Callback, button2Text, button2Callback, button3Text, button3Callback, destroyOnCallback, modalInfo)
919 -- if there is a callback and destroy not specified, assume destroy
920 if (destroyOnCallback == nil) and (button1Callback or button2Callback or button3Callback) then
921 destroyOnCallback = true
922 end
923
924 local dialog = Group(parent, "quickDialogGroup")
925
926 LayoutHelpers.AtCenterIn(dialog, parent)
927 dialog.Depth:Set(GetFrame(parent:GetRootFrame():GetTargetHead()):GetTopmostDepth() + 1)
928 local background = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_m.dds'))
929 dialog._background = background
930 dialog.Width:Set(background.Width)
931 dialog.Height:Set(background.Height)
932 LayoutHelpers.FillParent(background, dialog)
933
934 local textLine = {}
935 textLine[1] = CreateText(dialog, "", 18, titleFont)
936 textLine[1].Top:Set(background.Top)
937 LayoutHelpers.AtHorizontalCenterIn(textLine[1], dialog)
938
939 local textBoxWidth = (dialog.Width() - 80)
940 local tempTable = import('/lua/maui/text.lua').WrapText(LOC(dialogText), textBoxWidth,
941 function(text)
942 return textLine[1]:GetStringAdvance(text)
943 end)
944
945 local tempLines = table.getn(tempTable)
946
947 local prevControl = false
948 for i, v in tempTable do
949 if i == 1 then
950 textLine[1]:SetText(v)
951 prevControl = textLine[1]
952 else
953 textLine[i] = CreateText(dialog, v, 18, titleFont)
954 LayoutHelpers.Below(textLine[i], prevControl)
955 LayoutHelpers.AtHorizontalCenterIn(textLine[i], dialog)
956 prevControl = textLine[i]
957 end
958 end
959
960 background:SetTiled(true)
961 background.Bottom:Set(textLine[tempLines].Bottom)
962
963 local backgroundTop = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_T.dds'))
964 backgroundTop.Bottom:Set(background.Top)
965 backgroundTop.Left:Set(background.Left)
966 local backgroundBottom = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_b.dds'))
967 backgroundBottom.Top:Set(background.Bottom)
968 backgroundBottom.Left:Set(background.Left)
969
970 background.brackets = CreateDialogBrackets(background, 35, 65, 35, 115, true)
971
972 if not modalInfo or modalInfo.worldCover then
973 CreateWorldCover(dialog)
974 end
975
976 local function MakeButton(text, callback)
977 local button = CreateButtonStd( background
978 , '/scx_menu/small-btn/small'
979 , text
980 , 14
981 , 2)
982 if callback then
983 button.OnClick = function(self)
984 callback()
985 if destroyOnCallback then
986 dialog:Destroy()
987 end
988 end
989 else
990 button.OnClick = function(self)
991 dialog:Destroy()
992 end
993 end
994 return button
995 end
996
997 dialog._button1 = false
998 dialog._button2 = false
999 dialog._button3 = false
1000
1001 if button1Text then
1002 dialog._button1 = MakeButton(button1Text, button1Callback)
1003 LayoutHelpers.Below(dialog._button1, background, 0)
1004 end
1005 if button2Text then
1006 dialog._button2 = MakeButton(button2Text, button2Callback)
1007 LayoutHelpers.Below(dialog._button2, background, 0)
1008 end
1009 if button3Text then
1010 dialog._button3 = MakeButton(button3Text, button3Callback)
1011 LayoutHelpers.Below(dialog._button3, background, 0)
1012 end
1013
1014 if dialog._button3 then
1015 -- center each button to one third of the dialog
1016 LayoutHelpers.AtHorizontalCenterIn(dialog._button2, dialog)
1017 LayoutHelpers.LeftOf(dialog._button1, dialog._button2, -8)
1018 LayoutHelpers.ResetLeft(dialog._button1)
1019 LayoutHelpers.RightOf(dialog._button3, dialog._button2, -8)
1020 backgroundTop:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_T.dds'))
1021 backgroundBottom:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_b.dds'))
1022 background:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_m.dds'))
1023 -- Assign joystick navigation info
1024 dialog._button1:SetupJoystickNavigation(dialog._button3, dialog._button2, dialog._button3, dialog._button2)
1025 dialog._button2:SetupJoystickNavigation(dialog._button1, dialog._button3, dialog._button1, dialog._button3)
1026 dialog._button3:SetupJoystickNavigation(dialog._button2, dialog._button1, dialog._button2, dialog._button1)
1027 -- Assign default hilited button
1028 dialog._button1:TakeJoystickFocus()
1029 elseif dialog._button2 then
1030 -- center each button to half the dialog
1031 dialog._button1.Left:Set(function()
1032 return dialog.Left() + (((dialog.Width() / 2) - dialog._button1.Width()) / 2) + 8
1033 end)
1034 dialog._button2.Left:Set(function()
1035 local halfWidth = dialog.Width() / 2
1036 return dialog.Left() + halfWidth + ((halfWidth - dialog._button2.Width()) / 2) - 8
1037 end)
1038 -- Assign joystick navigation info
1039 dialog._button1:SetupJoystickNavigation(dialog._button2, dialog._button2, dialog._button2, dialog._button2)
1040 dialog._button2:SetupJoystickNavigation(dialog._button1, dialog._button1, dialog._button1, dialog._button1)
1041 -- Assign default hilited button
1042 dialog._button1:TakeJoystickFocus()
1043 elseif dialog._button1 then
1044 LayoutHelpers.AtHorizontalCenterIn(dialog._button1, dialog)
1045 -- Assign default hilited button
1046 dialog._button1:TakeJoystickFocus()
1047 else
1048 backgroundBottom:SetTexture(UIFile('/dialogs/dialog/panel_bmp_alt_b.dds'))
1049 -- No default hilited button - dialog sees joystick presses instead.
1050 background.brackets:Hide()
1051 if takeFocus then
1052 dialog:TakeJoystickFocus()
1053 end
1054 end
1055
1056 if modalInfo and not modalInfo.OnlyWorldCover then
1057 local function OnEnterFunc()
1058 if modalInfo.enterButton then
1059 if modalInfo.enterButton == 1 then
1060 if dialog._button1 then
1061 dialog._button1.OnClick(dialog._button1)
1062 end
1063 elseif modalInfo.enterButton == 2 then
1064 if dialog._button2 then
1065 dialog._button2.OnClick(dialog._button2)
1066 end
1067 elseif modalInfo.enterButton == 3 then
1068 if dialog._button3 then
1069 dialog._button3.OnClick(dialog._button3)
1070 end
1071 end
1072 end
1073 end
1074
1075 local function OnEscFunc()
1076 if modalInfo.escapeButton then
1077 if modalInfo.escapeButton == 1 then
1078 if dialog._button1 then
1079 dialog._button1.OnClick(dialog._button1)
1080 end
1081 elseif modalInfo.escapeButton == 2 then
1082 if dialog._button2 then
1083 dialog._button2.OnClick(dialog._button2)
1084 end
1085 elseif modalInfo.escapeButton == 3 then
1086 if dialog._button3 then
1087 dialog._button3.OnClick(dialog._button3)
1088 end
1089 end
1090 end
1091 end
1092
1093 MakeInputModal(dialog, OnEnterFunc, OnEscFunc)
1094 end
1095
1096 return dialog
1097end
1098
1099function QuickDialog360(parent, dialogText, button1Info, button2Info, button3Info, destroyOnCallback, modalInfo)
1100 -- if there is a callback and destroy not specified, assume destroy
1101 if (destroyOnCallback == nil) and
1102 ((button1Info and button1Info.callback) or
1103 (button2Info and button2Info.callback) or
1104 (button3Info and button3Info.callback)) then
1105 destroyOnCallback = true
1106 end
1107
1108 local baseName= 'dialog_quit_480'
1109 if GetCurrentResolution() == '720' and GetLanguageFromXbox() == 'FR' then -- let the hacks begin!
1110 baseName= 'dialog_quit_480F'
1111 end
1112 local dialog = Group(parent, "quickDialog360Group")
1113 local layout = UIGetFileForRes('/dialogs/360/'..baseName..'/'..baseName..'_layout.lua')
1114 local layoutTable = import(layout()).layout
1115
1116 SetDialogActive(true)
1117 SaveCurrentControl()
1118 HideCursor()
1119 if not destroyOnCallback then
1120 dialog.OnDestroy= function(self)
1121 SetDialogActive(false)
1122 RestoreLastControl()
1123 ShowCursor()
1124 end
1125 end
1126
1127 LayoutHelpers.AtCenterIn(dialog, parent)
1128 dialog.Depth:Set(GetFrame(parent:GetRootFrame():GetTargetHead()):GetTopmostDepth() + 1)
1129 local background = Bitmap(dialog, UIGetFileForRes('/dialogs/360/'..baseName..'/panel_bmp_m.dds'))
1130 dialog._background = background
1131 dialog.Width:Set(background.Width)
1132 dialog.Height:Set(background.Height)
1133 LayoutHelpers.FillParent(background, dialog)
1134
1135 local textLine = {}
1136 textLine[1] = CreateText(dialog, "", Fonts.DialogBoxText.size, Fonts.DialogBoxText.fontName)
1137 textLine[1].Top:Set(background.Top)
1138 LayoutHelpers.AtHorizontalCenterIn(textLine[1], dialog)
1139
1140 local textBoxWidth = (dialog.Width() - 80)
1141 local tempTable = import('/lua/maui/text.lua').WrapText(LOC(dialogText), textBoxWidth,
1142 function(text)
1143 return textLine[1]:GetStringAdvance(text)
1144 end)
1145
1146 local tempLines = table.getn(tempTable)
1147
1148 local prevControl = false
1149 for i, v in tempTable do
1150 if i == 1 then
1151 textLine[1]:SetText(v)
1152 prevControl = textLine[1]
1153 else
1154 textLine[i] = CreateText(dialog, v, 18, titleFont)
1155 LayoutHelpers.Below(textLine[i], prevControl)
1156 LayoutHelpers.AtHorizontalCenterIn(textLine[i], dialog)
1157 prevControl = textLine[i]
1158 end
1159 LayoutHelpers.DepthOverParent(textLine[i], background)
1160 end
1161
1162 background:SetTiled(true)
1163 background.Bottom:Set(textLine[tempLines].Bottom)
1164
1165 local backgroundTop = Bitmap(dialog, UIGetFileForRes('/dialogs/360/'..baseName..'/panel_bmp_T.dds'))
1166 backgroundTop.Bottom:Set(background.Top)
1167 backgroundTop.Left:Set(background.Left)
1168 local backgroundBottom = Bitmap(dialog, UIGetFileForRes('/dialogs/360/'..baseName..'/panel_bmp_b.dds'))
1169 backgroundBottom.Top:Set(background.Bottom)
1170 backgroundBottom.Left:Set(background.Left)
1171
1172 if not modalInfo or modalInfo.worldCover then
1173 CreateWorldCover(dialog)
1174 end
1175
1176 dialog.ButtonList= {}
1177
1178 local function MakeButton(buttonInfo, placement)
1179 if not buttonInfo then
1180 return
1181 end
1182
1183 local buttonNameList= { 'l_A_button', 'l_X_Button copy', 'l_B_Button', 'l_2button_left', 'l_2button_right' }
1184
1185 local ButtonFileName= nil
1186 for j,bmap in ButtonIcons do
1187 if bmap[1] == buttonInfo.button then
1188 ButtonFileName= bmap[2]
1189 break
1190 end
1191 end
1192
1193 if ButtonFileName then
1194 local ctrl= Bitmap(background, ButtonFileName)
1195 ctrl.label= CreateText(ctrl, buttonInfo.text or "", Fonts.StandardButtonText.size, Fonts.StandardButtonText.fontName)
1196
1197 LayoutHelpers.AtLeftTopIn(ctrl, backgroundBottom,
1198 layoutTable[buttonNameList[placement]].left - layoutTable['panel_bmp_b'].left,
1199 layoutTable[buttonNameList[placement]].top - layoutTable['panel_bmp_b'].top)
1200
1201 LayoutHelpers.RightOf(ctrl.label, ctrl, 15)
1202 LayoutHelpers.AtVerticalCenterIn(ctrl.label, ctrl, 1)
1203
1204 LayoutHelpers.DepthOverParent(ctrl, background)
1205 LayoutHelpers.DepthOverParent(ctrl.label, background)
1206
1207 ctrl.info= buttonInfo
1208 table.insert(dialog.ButtonList, ctrl)
1209 return ctrl
1210 else
1211 return nil
1212 end
1213 end
1214
1215 local ValidButtons= 0
1216 for i, info in {button1Info, button2Info, button3Info} do
1217 if info then
1218 ValidButtons= ValidButtons + 1
1219 end
1220 end
1221 for i, info in {button1Info, button2Info, button3Info} do
1222 if info.button == 'A' then
1223 if ValidButtons == 3 then
1224 info.pos= 3
1225 else
1226 info.pos= 5
1227 end
1228 elseif info.button == 'B' then
1229 if ValidButtons == 3 then
1230 info.pos= 1
1231 else
1232 info.pos= 4
1233 end
1234 else
1235 if ValidButtons == 3 then
1236 info.pos= 2
1237 else
1238 info.pos= 3+i
1239 end
1240 end
1241 end
1242
1243 MakeButton(button1Info, button1Info.pos)
1244 MakeButton(button2Info, button2Info.pos)
1245 MakeButton(button3Info, button3Info.pos)
1246
1247 dialog.HandleEvent = function(self, event)
1248 for i,ctrl in dialog.ButtonList do
1249 if ((event.Type == ('JoystickButtonRelease')) and
1250 (event.JoystickButton == ctrl.info.button)) then
1251 if destroyOnCallback then
1252 SetDialogActive(false)
1253 RestoreLastControl()
1254 ShowCursor()
1255 end
1256 if ctrl.info.callback then
1257 ctrl.info.callback()
1258 end
1259 if destroyOnCallback then
1260 dialog:Destroy()
1261 end
1262 end
1263 end
1264-- Hack just for the self destruct box to hide when pausing the game.
1265 if ((modalInfo.startEscape) and (event.Type == ('JoystickButtonPress')) and
1266 (event.JoystickButton == 'Start')) then
1267 if destroyOnCallback then
1268 SetDialogActive(false)
1269 RestoreLastControl()
1270 ShowCursor()
1271 end
1272 if modalInfo.startEscape then
1273 modalInfo.startEscape()
1274 end
1275 if destroyOnCallback then
1276 dialog:Destroy()
1277 end
1278 return false
1279 end
1280 return true
1281 end
1282
1283 dialog:TakeJoystickFocus()
1284
1285 return dialog
1286end
1287function CreateWorldCover(parent, colorOverride)
1288 local NumFrame = GetNumRootFrames() - 1
1289 local worldCovers = {}
1290 for i = 0, NumFrame do
1291 local index = i
1292 if GetFrame(index) == parent:GetRootFrame() then
1293 worldCovers[index] = Bitmap(parent)
1294 worldCovers[index].ID = index
1295 worldCovers[index].OnDestroy = function(self)
1296 for h, x in worldCovers do
1297 if x and h != self.ID then
1298 x:Destroy()
1299 end
1300 end
1301 end
1302 worldCovers[index].OnHide = function(self, hidden)
1303 for h, x in worldCovers do
1304 if x and h != self.ID then
1305 x:SetHidden(hidden)
1306 end
1307 end
1308 end
1309 else
1310 worldCovers[index] = Bitmap(GetFrame(index))
1311 end
1312 worldCovers[index]:SetSolidColor(colorOverride or 'ff000000')
1313 LayoutHelpers.FillParent(worldCovers[index], GetFrame(index))
1314 worldCovers[index].Depth:Set(function() return parent.Depth() - 2 end)
1315 worldCovers[index]:SetAlpha(0)
1316 worldCovers[index]:SetNeedsFrameUpdate(true)
1317 worldCovers[index].OnFrame = function(self, delta)
1318 local targetAlpha = self:GetAlpha() + (delta * 1.5)
1319 if targetAlpha < .8 then
1320 self:SetAlpha(targetAlpha)
1321 else
1322 self:SetAlpha(.8)
1323 self:SetNeedsFrameUpdate(false)
1324 end
1325 end
1326 end
1327
1328 return worldCovers
1329end
1330
1331function ShowInfoDialog(parent, dialogText, buttonText, buttonCallback, destroyOnCallback)
1332 local dlg = QuickDialog(parent, dialogText, buttonText, buttonCallback, nil, nil, nil, nil, destroyOnCallback, {worldCover = false, enterButton = 1, escapeButton = 1})
1333 return dlg
1334end
1335
1336-- create a table of sequential file names (useful for loading animations)
1337function CreateSequentialFilenameTable(root, ext, first, last, numPlaces)
1338 local retTable = {}
1339 local formatString = string.format("%%s%%0%dd.%%s", numPlaces)
1340 for index = first, last do
1341 retTable[(index - first) + 1] = SkinnableFile(string.format(formatString, root, index, ext))
1342 end
1343 return retTable
1344end
1345
1346-- create a box which is controlled by its external borders, and gives access to the "client" area as well
1347function CreateBox(parent)
1348 local border = Border(parent)
1349 border:SetTextures(
1350 SkinnableFile('/game/generic_brd/generic_brd_vert_l.dds'),
1351 SkinnableFile('/game/generic_brd/generic_brd_horz_um.dds'),
1352 SkinnableFile('/game/generic_brd/generic_brd_ul.dds'),
1353 SkinnableFile('/game/generic_brd/generic_brd_ur.dds'),
1354 SkinnableFile('/game/generic_brd/generic_brd_ll.dds'),
1355 SkinnableFile('/game/generic_brd/generic_brd_lr.dds'))
1356 local clientArea = Bitmap(parent, SkinnableFile('/game/generic_brd/generic_brd_m.dds'))
1357 border:LayoutControlInside(clientArea)
1358 clientArea.Width:Set(function() return clientArea.Right() - clientArea.Left() end)
1359 clientArea.Height:Set(function() return clientAreat.Bottom() - clientArea.Top() end)
1360 return border, clientArea
1361end
1362
1363-- create borders around a control, with optional background
1364function CreateBorder(parent, addBg)
1365 local border = Border(parent)
1366 border:SetTextures(
1367 SkinnableFile('/game/generic_brd/generic_brd_vert_l.dds'),
1368 SkinnableFile('/game/generic_brd/generic_brd_horz_um.dds'),
1369 SkinnableFile('/game/generic_brd/generic_brd_ul.dds'),
1370 SkinnableFile('/game/generic_brd/generic_brd_ur.dds'),
1371 SkinnableFile('/game/generic_brd/generic_brd_ll.dds'),
1372 SkinnableFile('/game/generic_brd/generic_brd_lr.dds'))
1373 border:LayoutAroundControl(parent)
1374
1375 local bg = nil
1376 if addBg then
1377 bg = Bitmap(parent, SkinnableFile('/game/generic_brd/generic_brd_m.dds'))
1378 border:LayoutControlInside(bg)
1379 bg.Width:Set(function() return bg.Right() - bg.Left() end)
1380 bg.Height:Set(function() return bg.Bottom() - bg.Top() end)
1381 end
1382
1383 return border, bg
1384end
1385
1386function GetFactionIcon(factionIndex)
1387 return import('/lua/common/factions.lua').Factions[factionIndex + 1].Icon
1388end
1389
1390-- make sure you lay out text box before you attempt to set text
1391function CreateTextBox(parent)
1392 local box = ItemList(parent)
1393 box:SetFont(bodyFont, 14)
1394 box:SetColors(bodyColor, "black", highlightColor, "white")
1395 CreateVertScrollbarFor(box)
1396 return box
1397end
1398
1399function SetTextBoxText(textBox, text)
1400 textBox:DeleteAllItems()
1401 local wrapped = import('/lua/maui/text.lua').WrapText(LOC(text), textBox.Width(), function(curText) return textBox:GetStringAdvance(curText) end)
1402 for i, line in wrapped do
1403 textBox:AddItem(line)
1404 end
1405end
1406function ClearStandardNavControl()
1407 if not CurrentControls or not CurrentControls.parent then
1408 return
1409 end
1410 if CurrentControls.parent.OldHandleEvent then
1411 CurrentControls.parent.HandleEvent= CurrentControls.parent.OldHandleEvent
1412 CurrentControls.parent.OldHandleEvent= nil
1413 else
1414 CurrentControls.parent.HandleEvent= nil
1415 end
1416 if CurrentControls.ScreenGroup then
1417 CurrentControls.ScreenGroup:Destroy()
1418 CurrentControls.ScreenGroup= nil
1419 end
1420 CurrentControls= {}
1421 CurrentControls.parent= nil
1422end
1423
1424function CreateDialogBrackets(parent, leftOffset, topOffset, rightOffset, bottomOffset, altTextures)
1425 local ret = Group(parent)
1426
1427 if altTextures then
1428 ret.topleft = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-ul_bmp.dds'))
1429 ret.topright = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-ur_bmp.dds'))
1430 ret.bottomleft = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-ll_bmp.dds'))
1431 ret.bottomright = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-lr_bmp.dds'))
1432
1433 ret.topleftglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-glow-ul_bmp.dds'))
1434 ret.toprightglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-glow-ur_bmp.dds'))
1435 ret.bottomleftglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-glow-ll_bmp.dds'))
1436 ret.bottomrightglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets-small/bracket-glow-lr_bmp.dds'))
1437 else
1438 ret.topleft = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-ul_bmp.dds'))
1439 ret.topright = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-ur_bmp.dds'))
1440 ret.bottomleft = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-ll_bmp.dds'))
1441 ret.bottomright = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-lr_bmp.dds'))
1442
1443 ret.topleftglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-glow-ul_bmp.dds'))
1444 ret.toprightglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-glow-ur_bmp.dds'))
1445 ret.bottomleftglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-glow-ll_bmp.dds'))
1446 ret.bottomrightglow = Bitmap(ret, UIFile('/scx_menu/panel-brackets/bracket-glow-lr_bmp.dds'))
1447 end
1448
1449 ret.topleftglow.Depth:Set(function() return ret.topleft.Depth() - 1 end)
1450 ret.toprightglow.Depth:Set(function() return ret.topright.Depth() - 1 end)
1451 ret.bottomleftglow.Depth:Set(function() return ret.bottomleft.Depth() - 1 end)
1452 ret.bottomrightglow.Depth:Set(function() return ret.bottomright.Depth() - 1 end)
1453
1454 LayoutHelpers.AtCenterIn(ret.topleftglow, ret.topleft)
1455 LayoutHelpers.AtCenterIn(ret.toprightglow, ret.topright)
1456 LayoutHelpers.AtCenterIn(ret.bottomleftglow, ret.bottomleft)
1457 LayoutHelpers.AtCenterIn(ret.bottomrightglow, ret.bottomright)
1458
1459 ret.topleft.Left:Set(function() return parent.Left() - leftOffset end)
1460 ret.topleft.Top:Set(function() return parent.Top() - topOffset end)
1461
1462 ret.topright.Right:Set(function() return parent.Right() + rightOffset end)
1463 ret.topright.Top:Set(function() return parent.Top() - topOffset end)
1464
1465 ret.bottomleft.Left:Set(function() return parent.Left() - leftOffset end)
1466 ret.bottomleft.Bottom:Set(function() return parent.Bottom() + bottomOffset end)
1467
1468 ret.bottomright.Right:Set(function() return parent.Right() + rightOffset end)
1469 ret.bottomright.Bottom:Set(function() return parent.Bottom() + bottomOffset end)
1470
1471 ret:DisableHitTest(true)
1472 LayoutHelpers.FillParent(ret, parent)
1473
1474 return ret
1475end
1476function SetDialogActive(active)
1477 if not CurrentControls or not CurrentControls.list then
1478 return
1479 end
1480 if active then
1481 for i,ctrl in CurrentControls.list do
1482 if ctrl.UI then
1483 ctrl.UI:SetAlpha(0, true)
1484 end
1485 end
1486 else
1487 for i,ctrl in CurrentControls.list do
1488 if ctrl.UI then
1489 ctrl.UI:SetAlpha(1, true)
1490 end
1491 end
1492 end
1493end
1494
1495function GetStandardNavControl(key)
1496 if CurrentControls and CurrentControls.list then
1497 for i,ctrl in CurrentControls.list do
1498 if ctrl.key and ctrl.key == key then
1499 return ctrl
1500 end
1501 end
1502 end
1503 return nil
1504end
1505
1506-- Setup any global buttons which do NOT require joystick focus to trigger (for forward, back mostly)
1507function SetupStandardNavControl(Controls)
1508-- Controls=
1509-- {
1510-- parent= the parent control where these button events are caught
1511-- setupBorderPanels = true/false
1512-- list= list of buttons
1513-- {
1514-- text=
1515-- {
1516-- parent= GUI.BotBar,
1517-- name= "<LOC _Back>",
1518-- font= Fonts.General.fontName,
1519-- size= Fonts.General.size,
1520-- left= 100,
1521-- layoutFile= layout file name,
1522-- controlName= control name (from layout file),
1523-- }
1524-- event= 'JoystickButtonPress' or 'JoystickButtonRelease' or nil
1525-- button= joystick button name
1526-- callback= function to call when this button is pressed
1527-- }
1528-- }
1529
1530 local layout= UIGetFileForRes('/480/480_Button_Layouts/480_Button_Layouts_layout.lua')
1531 local layoutTable = import(layout()).layout
1532
1533 if CurrentControls then
1534 ClearStandardNavControl()
1535 end
1536
1537 CurrentControls= Controls
1538 if not CurrentControls.parent then
1539 return
1540 end
1541
1542 CurrentControls.ScreenGroup= CreateScreenGroup(CurrentControls.parent, "Standard controls group")
1543 if CurrentControls.depth then
1544 CurrentControls.ScreenGroup.Depth:Set(CurrentControls.depth)
1545 else
1546 CurrentControls.ScreenGroup.Depth:Set(CurrentControls.parent.Depth() + 100)
1547 end
1548
1549 if CurrentControls.setupBorderPanels then
1550 local OverrideTop= nil
1551 local OverrideBot= nil
1552 local OverrideLayout= nil
1553 if IsInGame() then
1554 local res
1555 local wideScreen
1556 res, wideScreen = GetScreenResolution()
1557 if res == '480' and wideScreen then
1558 OverrideTop= UIFile('/480/480W_Button_Layouts/top.dds')
1559 OverrideBot= UIFile('/480/480W_Button_Layouts/bottom.dds')
1560 OverrideLayout= SkinnableFile('/480/480W_Button_Layouts/480W_Button_Layouts_layout.lua')
1561 end
1562 end
1563 CurrentControls.panelTop = Bitmap(CurrentControls.ScreenGroup, OverrideTop or CurrentControls.topPanel or UIGetFileForRes('/480/480_Button_Layouts/top.dds'))
1564 LayoutHelpers.RelativeTo(CurrentControls.panelTop, CurrentControls.ScreenGroup, OverrideLayout or layout, CurrentControls.topPanelName or 'top', nil)
1565 LayoutHelpers.DimensionsRelativeTo(CurrentControls.panelTop, OverrideLayout or layout, CurrentControls.topPanelName or 'top')
1566 LayoutHelpers.DepthOverParent(CurrentControls.panelTop, CurrentControls.ScreenGroup)
1567
1568 CurrentControls.panelBot = Bitmap(CurrentControls.ScreenGroup, OverrideBot or CurrentControls.botPanel or UIGetFileForRes('/480/480_Button_Layouts/bottom.dds'))
1569 LayoutHelpers.RelativeTo(CurrentControls.panelBot, CurrentControls.ScreenGroup, OverrideLayout or layout, CurrentControls.botPanelName or 'bottom', nil)
1570 LayoutHelpers.DimensionsRelativeTo(CurrentControls.panelBot, OverrideLayout or layout, CurrentControls.botPanelName or 'bottom')
1571 LayoutHelpers.DepthOverParent(CurrentControls.panelBot, CurrentControls.ScreenGroup)
1572
1573 if OverrideLayout then
1574 LayoutHelpers.AtHorizontalCenterIn(CurrentControls.panelTop, CurrentControls.ScreenGroup)
1575 LayoutHelpers.AtHorizontalCenterIn(CurrentControls.panelBot, CurrentControls.ScreenGroup)
1576 end
1577 end
1578
1579 for i,ctrl in CurrentControls.list do
1580 ctrl.UI= Group(CurrentControls.ScreenGroup)
1581 if ctrl.text then
1582 local ButtonFileName= nil
1583 for j,bmap in ButtonIcons do
1584 if bmap[1] == ctrl.button then
1585 ButtonFileName= bmap[2]
1586 break
1587 end
1588 end
1589 if not ctrl.text.layoutFile then
1590 ctrl.text.layoutFile= layout
1591 end
1592 ctrl.textWidget= CreateText(ctrl.UI, ctrl.text.name or "", ctrl.text.size or Fonts.StandardButtonText.size, ctrl.text.font or Fonts.StandardButtonText.fontName)
1593 ctrl.textWidget:SetColor(ctrl.text.color or fontColor)
1594
1595 ctrl.buttonWidget= nil
1596 if ButtonFileName then
1597 ctrl.buttonWidget= Bitmap(ctrl.UI, ButtonFileName)
1598 if ctrl.text.layoutFile and ctrl.text.controlName then
1599 LayoutHelpers.LeftRelativeTo(ctrl.buttonWidget, ctrl.text.parent, ctrl.text.layoutFile, ctrl.text.controlName, nil, ctrl.text.left)
1600 LayoutHelpers.CenteredVerticallyRelativeTo(ctrl.buttonWidget, ctrl.text.parent, ctrl.text.layoutFile, ctrl.text.controlName, nil, ctrl.text.top)
1601 else
1602 LayoutHelpers.AtLeftIn(ctrl.buttonWidget, ctrl.text.parent or CurrentControls.parent, ctrl.text.left or 0)
1603 if ctrl.text.top then
1604 LayoutHelpers.AtTopIn(ctrl.buttonWidget, ctrl.text.parent or CurrentControls.parent, ctrl.text.top or 0)
1605 else
1606 LayoutHelpers.AtVerticalCenterIn(ctrl.buttonWidget, ctrl.text.parent or CurrentControls.parent)
1607 end
1608 end
1609 LayoutHelpers.DepthOverParent(ctrl.buttonWidget, ctrl.UI, 2)
1610 LayoutHelpers.RightOf(ctrl.textWidget, ctrl.buttonWidget, 10)
1611 LayoutHelpers.AtVerticalCenterIn(ctrl.textWidget, ctrl.buttonWidget, 1)
1612 else
1613 if ctrl.text.layoutFile and ctrl.text.controlName then
1614 LayoutHelpers.RelativeTo(ctrl.textWidget, ctrl.text.parent, ctrl.text.layoutFile, ctrl.text.controlName, nil, ctrl.text.top, ctrl.text.left)
1615 else
1616 LayoutHelpers.AtLeftIn(ctrl.textWidget, ctrl.text.parent or CurrentControls.parent, ctrl.text.left or 0)
1617 if ctrl.text.top then
1618 LayoutHelpers.AtTopIn(ctrl.textWidget, ctrl.text.parent or CurrentControls.parent, ctrl.text.top or 0)
1619 else
1620 LayoutHelpers.AtVerticalCenterIn(ctrl.textWidget, ctrl.text.parent or CurrentControls.parent, 1)
1621 end
1622 end
1623 end
1624 LayoutHelpers.DepthOverParent(ctrl.textWidget, ctrl.UI, 2)
1625 end
1626 end
1627
1628 if CurrentControls.parent.HandleEvent then
1629 CurrentControls.parent.OldHandleEvent= CurrentControls.parent.HandleEvent
1630 end
1631 CurrentControls.parent.HandleEvent = function(self, event)
1632 local eventHandled = false
1633
1634 if event.Type == 'JoystickAnalogMotion' then
1635 -- Handle Left Thumbstick control imitating DPadUp/DPadDown/DPadLeft/DPadRight button events
1636 local fakeEvent = HandleTriggerToButtonEmulation( event )
1637 if fakeEvent != {} then
1638 eventHandled = self:HandleEvent( fakeEvent )
1639 end
1640 return eventHandled
1641 end
1642
1643 for i,ctrl in CurrentControls.list do
1644 if ((ctrl.callback) and (not ctrl.UI:IsHidden()) and
1645 (event.Type == (ctrl.event or 'JoystickButtonRelease')) and
1646 (event.JoystickButton == ctrl.button)) then
1647
1648 local sound = Sound( { Cue = "UI_Menu_MouseDown", Bank = "Interface", } )
1649 if ctrl.button == 'B' then
1650 sound = Sound( { Cue = "UI_Back_MouseDown", Bank = "Interface", } )
1651 end
1652 PlaySound( sound )
1653 ctrl.callback()
1654 eventHandled= true;
1655 end
1656 end
1657 if CurrentControls.captureAllInput then
1658 eventHandled= true
1659 end
1660 if eventHandled then
1661 return eventHandled
1662 elseif CurrentControls.extraHandleEvent then
1663 CurrentControls.extraHandleEvent(CurrentControls.parent, event)
1664 elseif CurrentControls.parent.OldHandleEvent then
1665 return CurrentControls.parent.OldHandleEvent(CurrentControls.parent, event) -- Flakey, doesn't seem to work sometimes.
1666 end
1667 return false
1668 end
1669end
1670
1671local cAxisZeroRange = 3000
1672local cAxisThreshold = 6000
1673
1674LeftThumbstickEmulation = {
1675 bWaitForXAxisZero = false,
1676 bWaitForYAxisZero = false,
1677 lastXAxisEmulation = nil,
1678 lastYAxisEmulation = nil,
1679}
1680
1681-- Handle Left Thumbstick control imitating DPadUp/DPadDown/DPadLeft/DPadRight button events
1682function HandleLeftThumbstickDPadEmulation( event, queryOnly )
1683 local isQuery = queryOnly or false
1684 local fakeEvent = {}
1685
1686 if event.Type == 'JoystickAnalogMotion' then
1687 -- Left Thumbstick control imitating DPadUp/DPadDown/DPadLeft/DPadRight button events
1688 if event.JoystickAxis == 'LeftThumbstick' then
1689
1690 -- Handle X-Axis -- DPadLeft/Right
1691 if LeftThumbstickEmulation.bWaitForXAxisZero then
1692
1693 if event.JoystickX < cAxisZeroRange and event.JoystickX > -cAxisZeroRange then
1694 if LeftThumbstickEmulation.lastXAxisEmulation then
1695 fakeEvent.JoystickButton = LeftThumbstickEmulation.lastXAxisEmulation
1696 fakeEvent.Type = 'JoystickButtonRelease'
1697 fakeEvent.WasAnalogStick = true
1698 if not isQuery then
1699 LeftThumbstickEmulation.bWaitForXAxisZero = false
1700 LeftThumbstickEmulation.lastXAxisEmulation = nil
1701 end
1702 return fakeEvent
1703 end
1704 end
1705
1706 elseif not LeftThumbstickEmulation.bWaitForXAxisZero then
1707
1708 if event.JoystickX > cAxisThreshold then
1709 fakeEvent.Type = 'JoystickButtonPress'
1710 fakeEvent.JoystickButton = 'DPadRight'
1711 fakeEvent.WasAnalogStick = true
1712 if not isQuery then
1713 LeftThumbstickEmulation.lastXAxisEmulation = fakeEvent.JoystickButton
1714 LeftThumbstickEmulation.bWaitForXAxisZero = true
1715 end
1716 return fakeEvent
1717 elseif event.JoystickX < -cAxisThreshold then
1718 fakeEvent.Type = 'JoystickButtonPress'
1719 fakeEvent.JoystickButton = 'DPadLeft'
1720 fakeEvent.WasAnalogStick = true
1721 if not isQuery then
1722 LeftThumbstickEmulation.lastXAxisEmulation = fakeEvent.JoystickButton
1723 LeftThumbstickEmulation.bWaitForXAxisZero = true
1724 end
1725 return fakeEvent
1726 end
1727 end
1728
1729 -- Handle Y-Axis -- DPadUp/Down
1730 if LeftThumbstickEmulation.bWaitForYAxisZero then
1731
1732 if event.JoystickY < cAxisZeroRange and event.JoystickY > -cAxisZeroRange then
1733 if LeftThumbstickEmulation.lastYAxisEmulation then
1734 fakeEvent.JoystickButton = LeftThumbstickEmulation.lastYAxisEmulation
1735 fakeEvent.Type = 'JoystickButtonRelease'
1736 fakeEvent.WasAnalogStick = true
1737 if not isQuery then
1738 LeftThumbstickEmulation.bWaitForYAxisZero = false
1739 LeftThumbstickEmulation.lastYAxisEmulation = nil
1740 end
1741 return fakeEvent
1742 end
1743 end
1744
1745 elseif not LeftThumbstickEmulation.bWaitForYAxisZero then
1746
1747 if event.JoystickY > cAxisThreshold then
1748 fakeEvent.Type = 'JoystickButtonPress'
1749 fakeEvent.JoystickButton = 'DPadUp'
1750 fakeEvent.WasAnalogStick = true
1751 if not isQuery then
1752 LeftThumbstickEmulation.lastYAxisEmulation = fakeEvent.JoystickButton
1753 LeftThumbstickEmulation.bWaitForYAxisZero = true
1754 end
1755 return fakeEvent
1756 elseif event.JoystickY < -cAxisThreshold then
1757 fakeEvent.Type = 'JoystickButtonPress'
1758 fakeEvent.JoystickButton = 'DPadDown'
1759 fakeEvent.WasAnalogStick = true
1760 if not isQuery then
1761 LeftThumbstickEmulation.lastYAxisEmulation = fakeEvent.JoystickButton
1762 LeftThumbstickEmulation.bWaitForYAxisZero = true
1763 end
1764 return fakeEvent
1765 end
1766 end
1767 end
1768 end
1769
1770 return fakeEvent
1771
1772end
1773
1774
1775
1776local cTriggerZeroRange = 50
1777local cTriggerThreshold = 200
1778
1779TriggerEmulation = {
1780 bWaitForLeftZero = false,
1781 bWaitForRightZero = false,
1782 lastLeftEmulation = nil,
1783 lastRightEmulation = nil,
1784}
1785
1786-- Handle Left Thumbstick control imitating DPadUp/DPadDown/DPadLeft/DPadRight button events
1787function HandleTriggerToButtonEmulation( event, queryOnly )
1788 local isQuery = queryOnly or false
1789 local fakeEvent = {}
1790
1791 if event.Type == 'JoystickAnalogMotion' then
1792 -- Left Thumbstick control imitating DPadUp/DPadDown/DPadLeft/DPadRight button events
1793 if event.JoystickAxis == 'LeftTrigger' then
1794
1795 -- Handle X-Axis -- DPadLeft/Right
1796 if TriggerEmulation.bWaitForLeftZero then
1797
1798 if event.JoystickTrigger < cTriggerZeroRange then
1799 if TriggerEmulation.lastLeftEmulation then
1800 fakeEvent.JoystickButton = TriggerEmulation.lastLeftEmulation
1801 fakeEvent.Type = 'JoystickButtonRelease'
1802 fakeEvent.WasAnalogStick = true
1803 if not isQuery then
1804 TriggerEmulation.bWaitForLeftZero = false
1805 TriggerEmulation.lastLeftEmulation = nil
1806 end
1807 return fakeEvent
1808 end
1809 end
1810
1811 elseif not TriggerEmulation.bWaitForLeftZero then
1812
1813 if event.JoystickTrigger > cTriggerThreshold then
1814 fakeEvent.Type = 'JoystickButtonPress'
1815 fakeEvent.JoystickButton = 'LeftTrigger'
1816 fakeEvent.WasAnalogStick = true
1817 TriggerEmulation.lastLeftEmulation = fakeEvent.JoystickButton
1818 if not isQuery then
1819 TriggerEmulation.bWaitForLeftZero = true
1820 end
1821 return fakeEvent
1822 end
1823 end
1824 elseif event.JoystickAxis == 'RightTrigger' then
1825 -- Handle Y-Axis -- DPadUp/Down
1826 if TriggerEmulation.bWaitForRightZero then
1827
1828 if event.JoystickTrigger < cTriggerZeroRange then
1829 if TriggerEmulation.lastRightEmulation then
1830 fakeEvent.JoystickButton = TriggerEmulation.lastRightEmulation
1831 fakeEvent.Type = 'JoystickButtonRelease'
1832 fakeEvent.WasAnalogStick = true
1833 if not isQuery then
1834 TriggerEmulation.bWaitForRightZero = false
1835 TriggerEmulation.lastRightEmulation = nil
1836 end
1837 return fakeEvent
1838 end
1839 end
1840
1841 elseif not TriggerEmulation.bWaitForRightZero then
1842
1843 if event.JoystickTrigger > cTriggerThreshold then
1844 fakeEvent.Type = 'JoystickButtonPress'
1845 fakeEvent.JoystickButton = 'RightTrigger'
1846 fakeEvent.WasAnalogStick = true
1847 TriggerEmulation.lastRightEmulation = fakeEvent.JoystickButton
1848 if not isQuery then
1849 TriggerEmulation.bWaitForRightZero = true
1850 end
1851 return fakeEvent
1852 end
1853 end
1854 end
1855 end
1856
1857 return fakeEvent
1858
1859end
1860function ResetInGameRefCounters()
1861 for i, fadeInfo in FadeTable do
1862 fadeInfo.RefCount= 0
1863 end
1864 CursorHiddenRefCount= 0
1865end
1866
1867function controllerStateChange( plugedin )
1868 local function PauseIt()
1869 local pause=true;
1870 local time=0.0
1871
1872 while 1 do
1873 PauseSound("World",pause)
1874 PauseSound("Music", pause)
1875 PauseVoice("VO",pause)
1876 WaitSeconds(0.25)
1877 time = time + 0.25
1878 if( time>4.0 ) then
1879 break
1880 end
1881 end
1882
1883 LOG("all sounds paused")
1884 end
1885
1886 import('/lua/ui/dialogs/saveload.lua').SetControllerState(plugedin)
1887
1888 if not plugedin then
1889 if not import('/lua/ui/dialogs/exitdialog.lua').IsExitDialogOpen() and not SessionIsPaused() and
1890 not import('/lua/ui/dialogs/exitdialog.lua').DoNotPopupPauseMenu then
1891 import('/lua/ui/dialogs/exitdialog.lua').CreateDialog(false)
1892
1893 ForkThread(PauseIt);
1894
1895 end
1896 end
1897end
1898function SaveCurrentControl()
1899-- Use this instead of take joystick focus. Pass in a different ctrlRecord variable for each 'window'
1900-- Add/Remove capture pushes the ctrl onto a stack, so we'll be able to tell which ctrl to give focus
1901-- to when closing a window and still be assured the ctrl still exists.
1902 local CurCtrl= GetJoystickFocus()
1903 if CurCtrl then
1904 local OldDestroy= CurCtrl.OnDestroy
1905 CurCtrl.OnDestroy= function(self)
1906-- Remove all occurances of this control from the saved control stack
1907 local CtrlRemoved= true
1908 while CtrlRemoved do
1909 CtrlRemoved= false
1910 for i,ctrl in pairs(CurrentControlStack) do
1911 if ctrl == self then
1912-- LOG("a control was deleted")
1913 table.remove(CurrentControlStack, i)
1914 CtrlRemoved= true
1915 break;
1916 end
1917 end
1918 end
1919-- Call the old on destroy function
1920 if OldDestroy then
1921 OldDestroy(self)
1922 end
1923 end
1924 CurrentStackRefCount= CurrentStackRefCount + 1
1925 table.insert(CurrentControlStack, CurCtrl)
1926-- LOG("control inserted: " .. CurrentStackRefCount)
1927 else
1928 LOG("Warning, no control has focus!")
1929 CurrentStackRefCount= CurrentStackRefCount + 1
1930 end
1931end
1932
1933function RestoreLastControl()
1934 local lastCtrl= table.getn(CurrentControlStack)
1935 if lastCtrl > 0 then
1936 CurrentControlStack[lastCtrl]:TakeJoystickFocus()
1937 if lastCtrl == CurrentStackRefCount then
1938 table.remove(CurrentControlStack)
1939 end
1940 CurrentStackRefCount= CurrentStackRefCount - 1
1941-- LOG("control removed, " .. CurrentStackRefCount .. " left.")
1942 else
1943 LOG("Warning: RestoreLastControl called on an empty CurrentControlStack!!")
1944 CurrentStackRefCount= CurrentStackRefCount - 1
1945 if CurrentStackRefCount < 0 then
1946 CurrentStackRefCount= 0
1947 end
1948-- LOG(SCR_Traceback("Error stacktrace:"))
1949 end
1950end
1951
1952function returnFocusToGame( ruthless )
1953 local GamesFocus= import('/lua/ui/game/worldview.lua').viewLeft
1954 local layer_wheelCons = import('/lua/ui/game/construction.lua')
1955 local layer_wheelOrd = import('/lua/ui/game/orders.lua')
1956 local layer_wheelGrp = import('/lua/ui/game/groups.lua')
1957 local layer_queue = import('/lua/ui/game/queue.lua')
1958
1959--- TODO: if 'Ruthless', close all other layers. go direct to game. properly test this...
1960 if ruthless then
1961 layer_wheelCons.EndUnitGridNavigation()
1962 layer_wheelOrd.EndOrdersGridNavigation()
1963 layer_wheelGrp.EndGroupsGridNavigation()
1964 GamesFocus:TakeJoystickFocus();
1965 return
1966 end
1967
1968 if layer_wheelCons.IsWheelVisible() then
1969 import('/lua/ui/game/templateWheel.lua').EndTemplateWheelNavigation()
1970 import('/lua/ui/game/groups.lua').EndGroupsGridNavigation()
1971 import('/lua/ui/game/orders.lua').EndOrdersGridNavigation()
1972 import('/lua/ui/game/queue.lua').EndQueueGridNavigation()
1973 if not GetTutorialDisableConstructionWheel() then
1974 import('/lua/ui/game/construction.lua').BeginUnitGridNavigation()
1975 end
1976 elseif layer_wheelOrd.IsWheelVisible() then
1977 layer_wheelOrd.BeginOrdersGridNavigation()
1978 elseif layer_wheelGrp.IsWheelVisible() then
1979 layer_wheelGrp.BeginGroupsGridNavigation()
1980 elseif layer_queue.IsVisible() then
1981 layer_queue.BeginQueueGridNavigation();
1982 else
1983 GamesFocus:TakeJoystickFocus();
1984 end
1985
1986end
1987function displayShortSaveMsg()
1988-- LOG("calling displayShortSaveMsg()")
1989 local infoStr = "<LOC uisaveload_0098>Do not turn off your console or remove the storage device. Saving preferences..."
1990 local status = ShowSplashDialog(GetFrame(0), infoStr )
1991 return status
1992end
1993
1994local statusStrDialogSaving ="<LOC uisaveload_0098>Do not turn off your console or remove the storage device. Saving preferences..."
1995local statusStrDialogLoading="<LOC uisaveload_0097>Do not turn off your console or remove the storage device. Loading preferences..."
1996local statusStrDialogCorruptSaving="<LOC uisaveload_0100>Preference file corrupt. Re-writing file. Do not turn off Xbox 360."
1997
1998local statusDialogSave=false
1999local statusDialogLoad=false
2000local ShowDoNotTurnOffDeviceDialogThread=false
2001
2002function QuickDialogLocal(parent, dialogText, button1Text, button1Callback, button2Text, button2Callback, button3Text, button3Callback, destroyOnCallback, modalInfo)
2003 -- if there is a callback and destroy not specified, assume destroy
2004 if (destroyOnCallback == nil) and (button1Callback or button2Callback or button3Callback) then
2005 destroyOnCallback = true
2006 end
2007
2008 local dialog = Group(parent, "quickDialogGroup")
2009
2010 --SetDialogActive(true)
2011 --SaveCurrentControl()
2012 --HideCursor()
2013 dialog.OnDestroy= function(self)
2014 --SetDialogActive(false)
2015 --RestoreLastControl()
2016 --ShowCursor()
2017 end
2018
2019 LayoutHelpers.AtCenterIn(dialog, parent)
2020 dialog.Depth:Set(GetFrame(parent:GetRootFrame():GetTargetHead()):GetTopmostDepth() + 1)
2021 local background = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_m.dds'))
2022 dialog._background = background
2023 dialog.Width:Set(background.Width)
2024 dialog.Height:Set(background.Height)
2025 LayoutHelpers.FillParent(background, dialog)
2026
2027 local textLine = {}
2028 textLine[1] = CreateText(dialog, "", 18, titleFont)
2029 textLine[1].Top:Set(background.Top)
2030 LayoutHelpers.AtHorizontalCenterIn(textLine[1], dialog)
2031
2032 local textBoxWidth = (dialog.Width() - 80)
2033 local tempTable = import('/lua/maui/text.lua').WrapText(LOC(dialogText), textBoxWidth,
2034 function(text)
2035 return textLine[1]:GetStringAdvance(text)
2036 end)
2037
2038 local tempLines = table.getn(tempTable)
2039
2040 local prevControl = false
2041 for i, v in tempTable do
2042 if i == 1 then
2043 textLine[1]:SetText(v)
2044 prevControl = textLine[1]
2045 else
2046 textLine[i] = CreateText(dialog, v, 18, titleFont)
2047 LayoutHelpers.Below(textLine[i], prevControl)
2048 LayoutHelpers.AtHorizontalCenterIn(textLine[i], dialog)
2049 prevControl = textLine[i]
2050 end
2051 LayoutHelpers.DepthOverParent(textLine[i], background)
2052 end
2053
2054 background:SetTiled(true)
2055 background.Bottom:Set(textLine[tempLines].Bottom)
2056
2057 local backgroundTop = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_T.dds'))
2058 backgroundTop.Bottom:Set(background.Top)
2059 backgroundTop.Left:Set(background.Left)
2060 local backgroundBottom = Bitmap(dialog, SkinnableFile('/dialogs/dialog/panel_bmp_b.dds'))
2061 backgroundBottom.Top:Set(background.Bottom)
2062 backgroundBottom.Left:Set(background.Left)
2063
2064 if not modalInfo or modalInfo.worldCover then
2065 CreateWorldCover(dialog)
2066 end
2067
2068 local function MakeButton(text, callback)
2069 local button = CreateButtonStd( background
2070 , '/widgets/small'
2071 , text
2072 , 12
2073 , 0)
2074 if callback then
2075 button.OnClick = function(self)
2076 callback()
2077 if destroyOnCallback then
2078 dialog:Destroy()
2079 end
2080 end
2081 else
2082 button.OnClick = function(self)
2083 dialog:Destroy()
2084 end
2085 end
2086 LayoutHelpers.DepthOverParent(button, background)
2087 return button
2088 end
2089
2090 dialog._button1 = false
2091 dialog._button2 = false
2092 dialog._button3 = false
2093
2094 if button1Text then
2095 dialog._button1 = MakeButton(button1Text, button1Callback)
2096 LayoutHelpers.Below(dialog._button1, background, 22)
2097 end
2098 if button2Text then
2099 dialog._button2 = MakeButton(button2Text, button2Callback)
2100 LayoutHelpers.Below(dialog._button2, background, 22)
2101 end
2102 if button3Text then
2103 dialog._button3 = MakeButton(button3Text, button3Callback)
2104 LayoutHelpers.Below(dialog._button3, background, 22)
2105 end
2106
2107 if dialog._button3 then
2108 -- center each button to one third of the dialog
2109 LayoutHelpers.AtHorizontalCenterIn(dialog._button2, dialog)
2110 LayoutHelpers.LeftOf(dialog._button1, dialog._button2)
2111 LayoutHelpers.ResetLeft(dialog._button1)
2112 LayoutHelpers.RightOf(dialog._button3, dialog._button2)
2113 backgroundTop:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_T.dds'))
2114 backgroundBottom:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_b.dds'))
2115 background:SetTexture(SkinnableFile('/dialogs/dialog_02/panel_bmp_m.dds'))
2116 -- Assign joystick navigation info
2117 dialog._button1:SetupJoystickNavigation(dialog._button3, dialog._button2, dialog._button3, dialog._button2)
2118 dialog._button2:SetupJoystickNavigation(dialog._button1, dialog._button3, dialog._button1, dialog._button3)
2119 dialog._button3:SetupJoystickNavigation(dialog._button2, dialog._button1, dialog._button2, dialog._button1)
2120 -- Assign default hilited button
2121 --dialog._button1:TakeJoystickFocus()
2122 elseif dialog._button2 then
2123 -- center each button to half the dialog
2124 dialog._button1.Left:Set(function()
2125 return dialog.Left() + (((dialog.Width() / 2) - dialog._button1.Width()) / 2)
2126 end)
2127 dialog._button2.Left:Set(function()
2128 local halfWidth = dialog.Width() / 2
2129 return dialog.Left() + halfWidth + ((halfWidth - dialog._button2.Width()) / 2)
2130 end)
2131 -- Assign joystick navigation info
2132 dialog._button1:SetupJoystickNavigation(dialog._button2, dialog._button2, dialog._button2, dialog._button2)
2133 dialog._button2:SetupJoystickNavigation(dialog._button1, dialog._button1, dialog._button1, dialog._button1)
2134 -- Assign default hilited button
2135 --dialog._button1:TakeJoystickFocus()
2136 elseif dialog._button1 then
2137 LayoutHelpers.AtHorizontalCenterIn(dialog._button1, dialog)
2138 -- Assign default hilited button
2139 --dialog._button1:TakeJoystickFocus()
2140 else
2141 backgroundBottom:SetTexture(UIFile('/dialogs/dialog/panel_bmp_alt_b.dds'))
2142 -- No default hilited button - dialog sees joystick presses instead.
2143 --dialog:TakeJoystickFocus()
2144 end
2145
2146 dialog.HandleEvent = function(self, event)
2147 return true
2148 end
2149
2150 if modalInfo then
2151 local function OnEnterFunc()
2152 if modalInfo.enterButton then
2153 if modalInfo.enterButton == 1 then
2154 if dialog._button1 then
2155 dialog._button1.OnClick(dialog._button1)
2156 end
2157 elseif modalInfo.enterButton == 2 then
2158 if dialog._button2 then
2159 dialog._button2.OnClick(dialog._button2)
2160 end
2161 elseif modalInfo.enterButton == 3 then
2162 if dialog._button3 then
2163 dialog._button3.OnClick(dialog._button3)
2164 end
2165 end
2166 end
2167 end
2168
2169 local function OnEscFunc()
2170 if modalInfo.escapeButton then
2171 if modalInfo.escapeButton == 1 then
2172 if dialog._button1 then
2173 dialog._button1.OnClick(dialog._button1)
2174 end
2175 elseif modalInfo.escapeButton == 2 then
2176 if dialog._button2 then
2177 dialog._button2.OnClick(dialog._button2)
2178 end
2179 elseif modalInfo.escapeButton == 3 then
2180 if dialog._button3 then
2181 dialog._button3.OnClick(dialog._button3)
2182 end
2183 end
2184 end
2185 end
2186
2187-- MakeInputModal(dialog, OnEnterFunc, OnEscFunc)
2188 end
2189
2190 return dialog
2191end
2192
2193local DepthSize = 110000
2194local NeedStorageDeviceMsg2Thread=false
2195function SetDialogDepth(depth)
2196 if( depth>DepthSize ) then
2197 DepthSize=depth
2198 end
2199end
2200
2201function NeedStorageDeviceMsg2(NeedStorageDevice, info)
2202
2203 local Ready=false
2204 local strDialog=info
2205
2206-- local MainMenu = import('/lua/ui/menus/main.lua').CreateUI
2207-- MainMenu('hideAll')
2208
2209 if info==nil then
2210 strDialog = "<LOC SIGNIN_WARNING_004>To load or save your game preferences you must have a storage device and be signed in with a gamer profile."
2211 end
2212
2213 if( WorldIsLoading() ) then
2214 NeedStorageDeviceMsg2Thread=false
2215 return
2216 end
2217
2218 --LOG(" IN NeedStorageDeviceMsg2 ")
2219
2220 local quick=QuickDialog360(GetFrame(0), strDialog
2221 , {
2222 button = 'A',
2223 text = "<LOC _OK>",
2224 callback = function() Ready=true end,
2225 }
2226 , nil
2227 , nil
2228 , false
2229 , {escapeButton = 2, enterButton = 1, worldCover = false} )
2230 if( not quick ) then
2231 NeedStorageDeviceMsg2Thread=false
2232 return
2233 end
2234
2235 quick.Depth:Set( DepthSize )
2236
2237 --if xbox panel is up then hide the dialog (user could be selecting the storage device)
2238
2239 while not Ready do
2240 if( GetStorageDevice()!=0 ) then
2241 break
2242 end
2243 if XGetPanelState()==1 then
2244 quick:Hide()
2245 else
2246 quick:Show()
2247 end
2248 WaitSeconds(0.25)
2249 end
2250 quick:Destroy()
2251 if( NeedStorageDevice and XGetSignedInUser()~=-1 ) then
2252 AskForStorageDevice()
2253 end
2254
2255-- MainMenu('showAll')
2256 NeedStorageDeviceMsg2Thread=false
2257end
2258
2259local AskForStorageDeviceThread=false
2260function AskForStorageDevice()
2261 -- determine if a storage device is available
2262 --
2263 local StorageDevice = GetStorageDevice()
2264 if( StorageDevice==0 ) then
2265 XChooseStorageDevice()
2266 while( GetStorageDevice()==0 ) do
2267 WaitSeconds(0.5)
2268 -- Once panel is hidden, user has made a choice of storage device, or not
2269 --
2270 if( XGetPanelState()==1 ) then
2271 break
2272 end
2273 end
2274
2275 while XGetPanelState()!=0 do
2276 WaitSeconds(0.5)
2277 end
2278
2279 if( GetStorageDevice()>0 ) then
2280 if( HaveRoomToSavePreferences() ) then
2281 --LOG("in SavePreferences()")
2282 if( ShowDoNotTurnOffDeviceDialogThread==false ) then
2283 ShowDoNotTurnOffDeviceDialogThread=ForkThread(ShowDoNotTurnOffDeviceDialog, false)
2284 end
2285 --InternalSavePreferences()
2286 --LOG("OUT SavePreferences()")
2287 else
2288 if( PrompUserToChangeDeviceThread==nil or PrompUserToChangeDeviceThread==false ) then
2289 PrompUserToChangeDeviceThread = ForkThread(PrompUserToChangeDevice)
2290 end
2291 end
2292 else
2293 NeedStorageDeviceMsg2(false)
2294 end
2295 end
2296 AskForStorageDeviceThread=false
2297end
2298
2299local inShowDoNotTurnOffDeviceDialog=false
2300function ShowDoNotTurnOffDeviceDialog(isLoading)
2301
2302 if( inShowDoNotTurnOffDeviceDialog ) then
2303 return
2304 end
2305
2306 inShowDoNotTurnOffDeviceDialog=true;
2307
2308 if( not WorldIsLoading() ) then
2309
2310 local statusDialog
2311 if( isLoading ) then
2312 statusDialog = QuickDialogLocal(GetFrame(0), statusStrDialogLoading,
2313 nil, nil, nil, nil,
2314 nil, nil, nil, {worldCover = false, enterButton = 1, escapeButton = 1})
2315 else
2316 local FileInfo = XGetFileInfo( XGetPrefsFileName() )
2317 if( FileInfo ) then
2318-- if (XOpenReadContent( XGetPrefsFileName() )==false )then
2319-- statusDialog = QuickDialogLocal(GetFrame(0), statusStrDialogCorruptSaving,
2320-- nil, nil, nil, nil,
2321-- nil, nil, nil, {worldCover = false, enterButton = 1, escapeButton = 1})
2322-- else
2323 statusDialog = QuickDialogLocal(GetFrame(0), statusStrDialogSaving,
2324 nil, nil, nil, nil,
2325 nil, nil, nil, {worldCover = false, enterButton = 1, escapeButton = 1})
2326-- end
2327-- XCloseReadContent()
2328 else
2329 statusDialog = QuickDialogLocal(GetFrame(0), statusStrDialogSaving,
2330 nil, nil, nil, nil,
2331 nil, nil, nil, {worldCover = false, enterButton = 1, escapeButton = 1})
2332 end
2333 end
2334
2335 --Wait while the storage device unavailable dialog is showing
2336 --
2337 while( NeedStorageDeviceMsg2Thread ) do
2338 WaitSeconds(0.25)
2339 end
2340
2341 if( statusDialog ) then
2342 local parent = GetFrame(0)
2343 statusDialog.Depth:Set( DepthSize )
2344
2345 --PV cheap hack to make sure the Saving/Loading prefs dialog always draws on top of the pause menu
2346 --
2347 DepthSize = DepthSize + 50
2348 statusDialog:Show()
2349
2350 --LOG("in ShowDoNotTurnOffDeviceDialog()")
2351 WaitSeconds(0.5)
2352
2353 StartLoadingAnim(LoadingAnimEffects.SPINNING_EFFECT, isLoading)
2354
2355 if( isLoading ) then
2356 LoadPreferences()
2357 else
2358 InternalSavePreferences()
2359 end
2360
2361 WaitSeconds(2.50)
2362 StopLoadingAnim()
2363
2364 statusDialog:Destroy()
2365 FlushEvents()
2366 end
2367
2368 end
2369
2370
2371 ShowDoNotTurnOffDeviceDialogThread=false;
2372 inShowDoNotTurnOffDeviceDialog=false;
2373end
2374
2375function ChangeDeviceNoRoom()
2376 XChooseStorageDevice(1)
2377 while( GetStorageDevice()==0 ) do
2378 WaitSeconds(0.5)
2379 -- Once panel is hidden, user has made a choice of storage device
2380 --
2381 if( XGetPanelState()==1 ) then
2382 break
2383 end
2384 end
2385
2386 while XGetPanelState()!=0 do
2387 WaitSeconds(0.5)
2388 end
2389
2390 -- User has not choosen a storage device (stupid git)
2391 --
2392 if( GetStorageDevice()==0 ) then
2393 NeedStorageDeviceMsg2(false)
2394 end
2395end
2396
2397local DeviceChangeCount=-1
2398PrompUserToChangeDeviceThread=false
2399function PrompUserToChangeDevice()
2400
2401 local infoStr = "<LOC uisaveload_0099>Insufficent room on storage device to save your preferences!"
2402
2403 while(1) do
2404 local Ready=false
2405 local DoChangeDevice=false
2406 local count = XGetStorageDeviceCount()
2407
2408 local quick=QuickDialog360(GetFrame(0), infoStr
2409 , {
2410 button = 'Y',
2411 text ="<LOC _Device>Change Device",
2412 callback = function()
2413 Ready=true
2414 DoChangeDevice=true
2415 end,
2416 }
2417 , {
2418 button = 'A',
2419 text = "<LOC _OK>",
2420 callback = function()
2421 Ready=true
2422 end,
2423 }
2424 , nil
2425 , nil
2426 , true
2427 , {escapeButton = 2, enterButton = 1, worldCover = false} )
2428
2429 while not Ready do
2430 WaitSeconds(0.5)
2431 end
2432
2433 quick:Destroy()
2434
2435 if( DoChangeDevice ) then
2436 ChangeDeviceNoRoom()
2437 if( GetStorageDevice()==0 ) then
2438 break
2439 end
2440 end
2441
2442 if( HaveRoomToSavePreferences() ) then
2443 if( ShowDoNotTurnOffDeviceDialogThread==false ) then
2444 ShowDoNotTurnOffDeviceDialogThread=ForkThread(ShowDoNotTurnOffDeviceDialog, false)
2445 end
2446 --InternalSavePreferences()
2447 break;
2448 else
2449 if( not DoChangeDevice ) then
2450 break;
2451 end
2452 end
2453
2454 end --while(1) do
2455 PrompUserToChangeDeviceThread=false
2456end --function PrompUserToChangeDevice()...
2457
2458function StartDoingPrefSaves(state)
2459 SetFrontEndData("PrefSaveEnabled", state)
2460 --LOG("PrefSaveEnabled="..repr(state))
2461end
2462
2463function SetWarnedOnce(state)
2464 SetFrontEndData("WarnedOnce", state)
2465end
2466
2467function MonitorSignIn()
2468 if( XGetSignedInUser()!=-1 ) then
2469
2470 end
2471end
2472
2473function SavePreferences()
2474
2475 --LOG("before SavePreferences()")
2476 local PrefSaveEnabled = GetFrontEndData("PrefSaveEnabled")
2477 if( PrefSaveEnabled==nil or PrefSaveEnabled==false ) then
2478 --LOG(" SavePreferences() false or nil")
2479 return
2480 end
2481
2482 if( IsDemoBuild() ) then
2483 return
2484 end
2485
2486 local StorageDevice = GetStorageDevice()
2487 local count = XGetStorageDeviceCount()
2488
2489 --LOG("in SavePreferences()..Count="..repr(count))
2490
2491 if( NeedStorageDeviceMsg2Thread ) then
2492 KillThread(NeedStorageDeviceMsg2Thread)
2493 NeedStorageDeviceMsg2Thread=false
2494 end
2495
2496 if( StorageDevice>0 ) then
2497 --LOG("in SavePreferences(): StorageDevice>0 ")
2498 if( HaveRoomToSavePreferences() ) then
2499 --LOG("in SavePreferences(): HaveRoomToSavePreferences()==true ")
2500 SetFrontEndData("WarnedOnce", false)
2501 --LOG("in SavePreferences()")
2502
2503 if( ShowDoNotTurnOffDeviceDialogThread==false ) then
2504 ShowDoNotTurnOffDeviceDialogThread=ForkThread(ShowDoNotTurnOffDeviceDialog, false)
2505 end
2506 --InternalSavePreferences()
2507 --LOG("OUT SavePreferences()")
2508 else
2509 local WarnedOnce = GetFrontEndData("WarnedOnce")
2510 --LOG("in SavePreferences(): HaveRoomToSavePreferences()==false ")
2511
2512 if( WarnedOnce==nil or WarnedOnce==false ) then
2513 --SetFrontEndData("WarnedOnce", true)
2514 DeviceChangeCount=count
2515 end
2516 if( ( WarnedOnce==nil or WarnedOnce==false or DeviceChangeCount!=count ) ) then
2517 if( PrompUserToChangeDeviceThread==nil or PrompUserToChangeDeviceThread==false ) then
2518 --LOG("in SavePreferences(): ( WarnedOnce==nil or WarnedOnce==false or DeviceChangeCount!=count )==true ")
2519 PrompUserToChangeDeviceThread = ForkThread(PrompUserToChangeDevice)
2520 end
2521 end
2522 end
2523 else
2524 local WarnedOnce = GetFrontEndData("WarnedOnce")
2525 --LOG("WarnedOnce.."..repr(WarnedOnce))
2526 LOG("in SavePreferences(): StorageDevice>0 (false) ")
2527 if( WarnedOnce==nil or WarnedOnce==false ) then
2528 --SetFrontEndData("WarnedOnce", true)
2529 --LOG("in SavePreferences(): ( WarnedOnce==nil or WarnedOnce==false )==true ")
2530 NeedStorageDeviceMsg2Thread=ForkThread(NeedStorageDeviceMsg2, true, "<LOC SIGNIN_WARNING_005>Storage Device unavailable.")
2531 DeviceChangeCount=count
2532 else
2533 --LOG("in SavePreferences(): ( WarnedOnce==nil or WarnedOnce==false )==false ")
2534 if( count!=DeviceChangeCount ) then
2535 DeviceChangeCount=count
2536 --LOG("in SavePreferences(): ( count!=DeviceChangeCount )==true")
2537 NeedStorageDeviceMsg2Thread=ForkThread(NeedStorageDeviceMsg2, true, "<LOC SIGNIN_WARNING_005>Storage Device unavailable.")
2538 --if( AskForStorageDeviceThread==false ) then
2539 -- AskForStorageDeviceThread=ForkThread(AskForStorageDevice)
2540 --end
2541 end
2542 end
2543 end
2544end