Download CommonLua/UI/LoadingScreen.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/UI/LoadingScreen.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/UI/LoadingScreen.lua
-
curl -L -o LoadingScreen.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/UI/LoadingScreen.lua
10.4 kB
| if FirstLoad then | |
| LoadingScreenTipsRate = 10000 | |
| LoadingScreenLog = {} | |
| end | |
| LoadingScreenOrgSize = point(1920, 1080) | |
| local lsprintf = CreatePrint{ | |
| --"loading screen", | |
| format = "printf", | |
| timestamp = true, | |
| } | |
| function LoadingScreenGetClassById(id) | |
| if id == "idSaveProfile" then | |
| return "BaseSavingScreen" | |
| elseif id == "idAutosaveScreen" then | |
| return "AutosaveScreen" | |
| elseif id == "idQuickSaveScreen" then | |
| return "QuickSaveScreen" | |
| end | |
| return "XLoadingScreen" | |
| end | |
| function GetLoadingScreenDialog(exceptAccountStorage) | |
| local dlg = GetDialog(LoadingScreenLog[#LoadingScreenLog]) | |
| if exceptAccountStorage and dlg then | |
| if not dlg.context or dlg.context.id ~= "idSaveProfile" then | |
| return dlg | |
| end | |
| else | |
| return dlg | |
| end | |
| end | |
| local function LoadingScreenCreate(class, id, reason, info_text, metadata) | |
| lsprintf("Creating: class = %s, id = %s, reason = %s", class, tostring(id), tostring(reason)) | |
| table.insert(LoadingScreenLog, class) | |
| local dlg = OpenDialog(class, nil, {id = id,reason = reason, info_text = info_text, metadata = metadata}, reason) | |
| --[[ | |
| -- the saving animation cannot be implemented using a transition effect | |
| if dlg.saving and rawget(dlg, "idSavingAnim") then | |
| dlg.idSavingAnim:CreateTransition{ | |
| keeprender = true, | |
| fadeIn = 500, | |
| fadeOut = 1000, | |
| angle = 360, angleRevert = true, angleTime = 1000, | |
| srcangle = 0, | |
| time = 500000, | |
| } | |
| end | |
| --]] | |
| if dlg.game_blocking then | |
| Pause(dlg) | |
| LockCamera(dlg) | |
| ChangeGameState("loading", true) | |
| if info_text and rawget(dlg, "idInfoText") then | |
| dlg.idInfoText:SetText(info_text) | |
| end | |
| local atTips = dlg.show_tips and (rawget(dlg, "idTips") or rawget(dlg, "idContainer") and rawget(dlg.idContainer, "idTips")) | |
| if atTips and tips.InitTips() then | |
| local last_tip_id = 0 | |
| local selected_tips = {} | |
| for i = 1, 5 do | |
| local tip, id | |
| repeat | |
| tip, id = tips.GetNextTip() | |
| until id ~= last_tip_id | |
| last_tip_id = id | |
| selected_tips[#selected_tips + 1] = _InternalTranslate(tip) | |
| end | |
| dlg:CreateThread(function() | |
| local idx = 1 | |
| while true do | |
| atTips:SetText(Untranslated(selected_tips[idx])) | |
| idx = (idx + 1) > #selected_tips and 1 or (idx + 1) | |
| Sleep(LoadingScreenTipsRate) | |
| end | |
| end) | |
| end | |
| end | |
| dlg.clock_opened = GetClock() | |
| return dlg | |
| end | |
| function LoadingScreenExecute(id, reason, func) | |
| LoadingScreenOpen(id, reason) | |
| local result = func() | |
| LoadingScreenClose(id, reason) | |
| return result | |
| end | |
| function LoadingScreenOpen(id, reason, first_tip, metadata) | |
| assert(IsRealTimeThread(), "The loading screen requires a real time thread") | |
| lsprintf("Opening %s, reason = %s", tostring(id), tostring(reason)) | |
| local class = LoadingScreenGetClassById(id) | |
| if not class then | |
| assert(false, "No loading screen class matches " .. tostring(id)) | |
| return | |
| end | |
| local dlg = GetDialog(class) | |
| if dlg and dlg.window_state == "closing" then | |
| local modifier = dlg:FindModifier("fade") | |
| if modifier then | |
| modifier.on_complete = function() end | |
| end | |
| dlg:delete() | |
| dlg = nil | |
| end | |
| dlg = dlg or LoadingScreenCreate(class, id, reason, first_tip, metadata) | |
| dlg:AddOpenReason(reason) | |
| lsprintf("Opened %s, reason = %s", tostring(id), tostring(reason)) | |
| if dlg.game_blocking then | |
| WaitNextFrame(5) -- wait for UI to be rendered | |
| end | |
| end | |
| function LoadingScreenClose(id, reason) | |
| lsprintf("Closing %s, reason = %s", tostring(id), tostring(reason)) | |
| local class = LoadingScreenGetClassById(id) | |
| local dlg = class and GetDialog(class) | |
| if not dlg then | |
| lsprintf("Closing %s cancelled, no dialog", tostring(id)) | |
| return | |
| end | |
| if not dlg:GetOpenReasons()[reason] then | |
| print("Trying to close a Loading/Saving screen with id/reason that aren't used for opening: " .. tostring(reason)) | |
| print("Active reasons:", table.concat(table.keys2(dlg:GetOpenReasons()), " ")) | |
| lsprintf("Closing %s cancelled, no reason", tostring(id)) | |
| return | |
| end | |
| if dlg:RemoveOpenReason(reason) then -- return true in case we should close the dialog | |
| lsprintf("Closing %s, no reasons left", tostring(id)) | |
| -- add the reason back to make sure LoadingScreenOpen doesn't try to open the same dialog | |
| dlg:AddOpenReason(reason) | |
| local parent_thread = CurrentThread() | |
| local game_blocking = dlg.game_blocking | |
| CreateRealTimeThread(function() | |
| while dlg.clock_opened == 0 do | |
| Sleep(17) | |
| end | |
| local clock_closed = dlg.clock_opened | |
| if dlg.saving then | |
| clock_closed = clock_closed + 3141 | |
| elseif game_blocking then | |
| clock_closed = clock_closed + (dlg.close_delay or 1200) | |
| end | |
| lsprintf("Closing %s, waiting clock", tostring(id)) | |
| while GetClock() - clock_closed < 0 do | |
| Sleep(30) | |
| end | |
| -- check if we still need to close the dialog | |
| lsprintf("Closing %s, checking for reopen", tostring(id)) | |
| if dlg:RemoveOpenReason(reason) then | |
| lsprintf("Closing %s, final closing", tostring(id)) | |
| if game_blocking then | |
| -- if there are other loading screens opened at the moment, don't bother with the render mode, the last one will take care | |
| local dlgs = ListDialogs() | |
| local unblock = true | |
| for i = 1, #dlgs do | |
| local d = GetDialog(dlgs[i]) | |
| if d ~= dlg and d:IsKindOf("BaseLoadingScreen") and d.game_blocking then | |
| unblock = false | |
| break | |
| end | |
| end | |
| if unblock and GetMap() ~= "" then | |
| if not dlg.saving then | |
| WaitNextFrame(3) | |
| SetupViews() | |
| end | |
| end | |
| ChangeGameState("loading", not unblock) | |
| UnlockCamera(dlg) | |
| Resume(dlg) | |
| end | |
| --assert(next(dlg.ids_and_reasons) == nil, "Loading screen reopened too soon after being closed! Please use a single screen that encompasses both operations!") | |
| -- Recheck again if we should close: while waiting for "scene" render mode above, someone could have closed it | |
| if not next(dlg:GetOpenReasons()) then | |
| -- Give a chance to those who want to open something before the loading screen closes | |
| Msg("LoadingScreenPreClose") | |
| WaitNextFrame() | |
| -- Recheck again if we should close: while waiting above, someone could have added a new open reason | |
| if not next(dlg:GetOpenReasons()) then | |
| if dlg.window_state ~= "destroying" then | |
| dlg:Close("final") | |
| table.remove_entry(LoadingScreenLog, class) | |
| end | |
| lsprintf("Closed %s, reason = %s", tostring(id), tostring(reason)) | |
| end | |
| end | |
| if next(dlg:GetOpenReasons()) then | |
| lsprintf("Cancelled closing, we have a new reason to live", next(dlg:GetOpenReasons())) | |
| end | |
| end | |
| if game_blocking then | |
| Wakeup(parent_thread) | |
| end | |
| end) | |
| if game_blocking then | |
| WaitWakeup() | |
| end | |
| end | |
| end | |
| DefineClass.BaseLoadingScreen = { | |
| __parents = { "XDialog" }, | |
| properties = { | |
| { category = "LoadingScreen", id = "game_blocking", editor = "bool", default = true, }, | |
| }, | |
| clock_opened = 0, | |
| close_delay = false, | |
| saving = false, | |
| show_tips = true, | |
| ZOrder = 1000000000, | |
| MouseCursor = "CommonAssets/UI/waitcursor.tga", | |
| HandleMouse = true, | |
| image = "UI/SplashScreen.tga", | |
| transparent = false, | |
| FocusOnOpen = "", | |
| } | |
| function BaseLoadingScreen:Open(...) | |
| XDialog.Open(self, ...) | |
| ShowMouseCursor("Loading screen") | |
| if self.game_blocking then | |
| self:SetModal() | |
| self:SetFocus() | |
| end | |
| if self.transparent then | |
| self:SetMouseCursor(false) | |
| self.HandleMouse = false | |
| self.ChildrenHandleMouse = false | |
| end | |
| if rawget(self, "idImage") then | |
| self.idImage:SetImage(self.image) | |
| end | |
| end | |
| function BaseLoadingScreen:OnShortcut(shortcut, source, ...) | |
| if (Platform.publisher or Platform.developer) and shortcut == "Ctrl-F1" then | |
| return "continue" -- allow bug reporter | |
| end | |
| if self.game_blocking and not AreMessageBoxesOpen() then | |
| return "break" | |
| end | |
| end | |
| function BaseLoadingScreen:Close(result) | |
| if result == "final" then | |
| HideMouseCursor("Loading screen") | |
| XWindow.Close(self) | |
| end | |
| end | |
| DefineClass.BaseSavingScreen = { | |
| __parents = { "BaseLoadingScreen" }, | |
| saving = true, | |
| game_blocking = false, | |
| image = false, | |
| transparent = true, | |
| } | |
| function GetOpenLoadingScreen(id) | |
| local class = LoadingScreenGetClassById(id) | |
| return class and GetDialog(class) and true or false | |
| end | |
| function DrawSplashScreen() | |
| -- stub, redefine per project | |
| -- ATTN: this is called before the initialization of the classes system, only use pure UIL calls | |
| -- mimic the bink player behavior, stretch full screen | |
| -- do not measure the image size, because in some cases this fails, use 16:9 image | |
| local screen = UIL.GetScreenSize() | |
| local size = ScaleToFit(LoadingScreenOrgSize, screen, not "clip") | |
| local pos = (screen - size) / 2 | |
| local rc = box(pos, pos + size) | |
| UIL.DrawSolidRect(box(point20, screen), RGB(0,0,0)) | |
| UIL.DrawImage("UI/SplashScreen.tga", rc) | |
| end | |
| DefineClass.XLoadingScreenClass = | |
| { | |
| __parents = { "BaseLoadingScreen" }, | |
| FadeOutTime = 300, | |
| Background = RGB(0, 0, 0), | |
| } | |
| g_LoadingScreens = { | |
| "UI/SplashScreen.tga", | |
| } | |
| if FirstLoad then | |
| g_FirstLoadingScreen = true | |
| end | |
| function XLoadingScreenClass:Open(...) | |
| self.image = g_FirstLoadingScreen and "UI/SplashScreen.tga" or table.rand(g_LoadingScreens) | |
| g_FirstLoadingScreen = false | |
| BaseLoadingScreen.Open(self, ...) | |
| end | |
| function GetGameBlockingLoadingScreen() | |
| for _, d in pairs(Dialogs) do | |
| if d and IsKindOf(d, "BaseLoadingScreen") and d.game_blocking then | |
| return d | |
| end | |
| end | |
| end | |
| function WaitLoadingScreenClose() -- only checks for game blocking loading screens | |
| while GetGameBlockingLoadingScreen() do | |
| WaitNextFrame() | |
| end | |
| end | |
| --[[ | |
| --test cases | |
| function SST_CloseAndReopen() | |
| CreateRealTimeThread(function() | |
| LoadingScreenOpen("idSavingScreen") | |
| Sleep(1000) -- write something | |
| LoadingScreenClose("idSavingScreen") | |
| assert(GetOpenLoadingScreen("idSavingScreen")) | |
| Sleep(3000) | |
| assert(GetOpenLoadingScreen("idSavingScreen")) | |
| LoadingScreenOpen("idSavingScreen") | |
| Sleep(1000) | |
| LoadingScreenClose("idSavingScreen") | |
| Sleep(499) | |
| assert(GetOpenLoadingScreen("idSavingScreen")) -- should stay for 500 ms after the last 'Close' | |
| Sleep(2) | |
| assert(not GetOpenLoadingScreen("idSavingScreen")) -- and still be closed properly (more than 4 seconds have passed since it has been opened) | |
| end) | |
| end | |
| function SST_OpenCloseAndChangeMap(map) | |
| CreateRealTimeThread(function() | |
| LoadingScreenOpen("idSavingScreen", "test") | |
| Sleep(1000) -- write something | |
| LoadingScreenClose("idSavingScreen", "test") | |
| print("changing map, the saving screen should disappear in ~3 sec") | |
| ChangeMap(map) | |
| end) | |
| end | |
| --]] |