From 7c4be9ce928d635e87440d4a6c4cf6378a28a912 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 24 Apr 2024 18:31:00 +0200 Subject: [PATCH 1/9] Introduce PreloaderScene for game initialisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ζeh Matt <5415177+ZehMatt@users.noreply.github.com> --- src/openrct2/Context.cpp | 50 +++++++------- src/openrct2/Context.h | 2 +- src/openrct2/core/JobPool.cpp | 6 ++ src/openrct2/core/JobPool.h | 1 + src/openrct2/libopenrct2.vcxproj | 4 +- src/openrct2/scenes/Scene.cpp | 14 ++++ src/openrct2/scenes/Scene.h | 7 ++ .../scenes/preloader/PreloaderScene.cpp | 68 +++++++++++++++++++ .../scenes/preloader/PreloaderScene.h | 34 ++++++++++ 9 files changed, 160 insertions(+), 26 deletions(-) create mode 100644 src/openrct2/scenes/preloader/PreloaderScene.cpp create mode 100644 src/openrct2/scenes/preloader/PreloaderScene.h diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 08ce5d777c..401c80514a 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -68,6 +68,7 @@ #include "scenario/ScenarioRepository.h" #include "scenes/game/GameScene.h" #include "scenes/intro/IntroScene.h" +#include "scenes/preloader/PreloaderScene.h" #include "scenes/title/TitleScene.h" #include "scenes/title/TitleSequenceManager.h" #include "scripting/HookEngine.h" @@ -124,6 +125,7 @@ namespace OpenRCT2 #endif // Scenes + std::unique_ptr _preloaderScene; std::unique_ptr _introScene; std::unique_ptr _titleScene; std::unique_ptr _gameScene; @@ -175,6 +177,7 @@ namespace OpenRCT2 #ifndef DISABLE_NETWORK , _network(*this) #endif + , _preloaderScene(std::make_unique(*this)) , _introScene(std::make_unique(*this)) , _titleScene(std::make_unique(*this)) , _gameScene(std::make_unique(*this)) @@ -311,10 +314,9 @@ namespace OpenRCT2 return EXIT_FAILURE; } - IScene* GetLoadingScene() override + IScene* GetPreloaderScene() override { - // TODO: Implement me. - return nullptr; + return _preloaderScene.get(); } IScene* GetIntroScene() override @@ -477,26 +479,6 @@ namespace OpenRCT2 EnsureUserContentDirectoriesExist(); - // TODO Ideally we want to delay this until we show the title so that we can - // still open the game window and draw a progress screen for the creation - // of the object cache. - _objectRepository->LoadOrConstruct(_localisationService->GetCurrentLanguage()); - - if (!gOpenRCT2Headless) - { - _assetPackManager->Scan(); - _assetPackManager->LoadEnabledAssetPacks(); - _assetPackManager->Reload(); - } - - // TODO Like objects, this can take a while if there are a lot of track designs - // its also really something really we might want to do in the background - // as its not required until the player wants to place a new ride. - _trackDesignRepository->Scan(_localisationService->GetCurrentLanguage()); - - _scenarioRepository->Scan(_localisationService->GetCurrentLanguage()); - TitleSequenceManager::Scan(); - if (!gOpenRCT2Headless) { Audio::Init(); @@ -520,7 +502,27 @@ namespace OpenRCT2 InputResetPlaceObjModifier(); ViewportInitAll(); - gameStateInitAll(GetGameState(), DEFAULT_MAP_SIZE); + ContextInit(); + + _preloaderScene->AddJob([&]() { + _objectRepository->LoadOrConstruct(_localisationService->GetCurrentLanguage()); + + if (!gOpenRCT2Headless) + { + _assetPackManager->Scan(); + _assetPackManager->LoadEnabledAssetPacks(); + _assetPackManager->Reload(); + } + + _trackDesignRepository->Scan(_localisationService->GetCurrentLanguage()); + + _scenarioRepository->Scan(_localisationService->GetCurrentLanguage()); + }); + + TitleSequenceManager::Scan(); + + _preloaderScene->SetCompletionScene(GetTitleScene()); + SetActiveScene(_preloaderScene.get()); #ifdef ENABLE_SCRIPTING _scriptEngine.Initialise(); diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index 8f3b463008..95000ddbd2 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -144,7 +144,7 @@ namespace OpenRCT2 virtual NetworkBase& GetNetwork() abstract; #endif - virtual IScene* GetLoadingScene() abstract; + virtual IScene* GetPreloaderScene() abstract; virtual IScene* GetIntroScene() abstract; virtual IScene* GetTitleScene() abstract; virtual IScene* GetGameScene() abstract; diff --git a/src/openrct2/core/JobPool.cpp b/src/openrct2/core/JobPool.cpp index e4038663ab..ca757ca3fa 100644 --- a/src/openrct2/core/JobPool.cpp +++ b/src/openrct2/core/JobPool.cpp @@ -95,6 +95,12 @@ size_t JobPool::CountPending() return _pending.size(); } +size_t JobPool::CountProcessing() +{ + unique_lock lock(_mutex); + return _processing; +} + void JobPool::ProcessQueue() { unique_lock lock(_mutex); diff --git a/src/openrct2/core/JobPool.h b/src/openrct2/core/JobPool.h index aa558929fc..bfd51ad71c 100644 --- a/src/openrct2/core/JobPool.h +++ b/src/openrct2/core/JobPool.h @@ -46,6 +46,7 @@ public: void AddTask(std::function workFn, std::function completionFn = nullptr); void Join(std::function reportFn = nullptr); size_t CountPending(); + size_t CountProcessing(); private: void ProcessQueue(); diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 6f9af5f1bb..9bfa837ac4 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -522,8 +522,9 @@ - + + @@ -1015,6 +1016,7 @@ + diff --git a/src/openrct2/scenes/Scene.cpp b/src/openrct2/scenes/Scene.cpp index 8f2681b29e..6e8316548a 100644 --- a/src/openrct2/scenes/Scene.cpp +++ b/src/openrct2/scenes/Scene.cpp @@ -28,3 +28,17 @@ GameState_t& Scene::GetGameState() { return OpenRCT2::GetGameState(); } + +void Scene::FinishScene() +{ + if (_nextScene != nullptr) + { + _context.SetActiveScene(_nextScene); + _nextScene = nullptr; + } +} + +void Scene::SetCompletionScene(IScene* scene) +{ + _nextScene = scene; +} diff --git a/src/openrct2/scenes/Scene.h b/src/openrct2/scenes/Scene.h index 4e1e135d88..6e7c5edd12 100644 --- a/src/openrct2/scenes/Scene.h +++ b/src/openrct2/scenes/Scene.h @@ -27,6 +27,7 @@ namespace OpenRCT2 virtual void Load() = 0; virtual void Tick() = 0; virtual void Stop() = 0; + virtual void SetCompletionScene(IScene* scene) = 0; }; class Scene : public IScene @@ -37,8 +38,14 @@ namespace OpenRCT2 GameState_t& GetGameState() override; IContext& GetContext() override; + void SetCompletionScene(IScene* scene) override; + + protected: + void FinishScene(); + protected: IContext& _context; + IScene* _nextScene = nullptr; }; } // namespace OpenRCT2 diff --git a/src/openrct2/scenes/preloader/PreloaderScene.cpp b/src/openrct2/scenes/preloader/PreloaderScene.cpp new file mode 100644 index 0000000000..969aaf3541 --- /dev/null +++ b/src/openrct2/scenes/preloader/PreloaderScene.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "PreloaderScene.h" + +#include "../../Context.h" +#include "../../Game.h" +#include "../../GameState.h" +#include "../../OpenRCT2.h" +#include "../../audio/audio.h" +#include "../../interface/Viewport.h" +#include "../../interface/Window.h" +#include "../../localisation/StringIds.h" +#include "../../windows/Intent.h" + +using namespace OpenRCT2; + +PreloaderScene::PreloaderScene(IContext& context) + : Scene(context) + , _jobs(1) +{ +} + +void PreloaderScene::Load() +{ + LOG_VERBOSE("PreloaderScene::Load()"); + + gScreenFlags = SCREEN_FLAGS_PLAYING; + gameStateInitAll(GetGameState(), DEFAULT_MAP_SIZE); + ViewportInitAll(); + ContextOpenWindow(WindowClass::MainWindow); + WindowResizeGui(ContextGetWidth(), ContextGetHeight()); + + auto intent = Intent(WindowClass::NetworkStatus); + intent.PutExtra(INTENT_EXTRA_MESSAGE, std::string{ "Loading..." }); + ContextOpenIntent(&intent); + + LOG_VERBOSE("PreloaderScene::Load() finished"); +} + +void PreloaderScene::Tick() +{ + gInUpdateCode = true; + + ContextHandleInput(); + WindowInvalidateAll(); + + gInUpdateCode = false; + + if (_jobs.CountPending() == 0 && _jobs.CountProcessing() == 0) + { + // Make sure the job is fully completed. + _jobs.Join(); + + FinishScene(); + } +} + +void PreloaderScene::Stop() +{ + Audio::StopAll(); +} diff --git a/src/openrct2/scenes/preloader/PreloaderScene.h b/src/openrct2/scenes/preloader/PreloaderScene.h new file mode 100644 index 0000000000..09324df707 --- /dev/null +++ b/src/openrct2/scenes/preloader/PreloaderScene.h @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../core/JobPool.h" +#include "../../drawing/Drawing.h" +#include "../Scene.h" + +namespace OpenRCT2 +{ + class PreloaderScene final : public Scene + { + public: + PreloaderScene(IContext& context); + + void Load() override; + void Tick() override; + void Stop() override; + void AddJob(const std::function& fn) + { + _jobs.AddTask(fn); + } + + private: + JobPool _jobs; + }; +} // namespace OpenRCT2 From 9f45d40baeb3df3e1b19b2c49066d5c309913187 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 24 Apr 2024 19:40:46 +0200 Subject: [PATCH 2/9] Add localisable progress status messages --- data/language/en-GB.txt | 5 +++++ src/openrct2/Context.cpp | 12 +++++++++--- src/openrct2/localisation/StringIds.h | 6 ++++++ src/openrct2/scenes/preloader/PreloaderScene.cpp | 14 +++++++++++--- src/openrct2/scenes/preloader/PreloaderScene.h | 1 + 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 487806c89f..636b35a5b9 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3702,6 +3702,11 @@ STR_6627 :Track speed too high! STR_6628 :Can only be placed on path edges! STR_6629 :Align toolbar buttons horizontally centred STR_6630 :This setting will align the toolbar buttons horizontally in the centre of the screen. The traditional way of aligning them is in the left and right corner. +STR_6631 :Loading... +STR_6632 :Checking object files... +STR_6633 :Checking scenario files... +STR_6634 :Checking track design files... +STR_6635 :Checking asset packs... ############# # Scenarios # diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 401c80514a..6784bc13d1 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -505,18 +505,24 @@ namespace OpenRCT2 ContextInit(); _preloaderScene->AddJob([&]() { - _objectRepository->LoadOrConstruct(_localisationService->GetCurrentLanguage()); + auto currentLanguage = _localisationService->GetCurrentLanguage(); + + _preloaderScene->UpdateCaption(STR_CHECKING_OBJECT_FILES); + _objectRepository->LoadOrConstruct(currentLanguage); if (!gOpenRCT2Headless) { + _preloaderScene->UpdateCaption(STR_CHECKING_ASSET_PACKS); _assetPackManager->Scan(); _assetPackManager->LoadEnabledAssetPacks(); _assetPackManager->Reload(); } - _trackDesignRepository->Scan(_localisationService->GetCurrentLanguage()); + _preloaderScene->UpdateCaption(STR_CHECKING_TRACK_DESIGN_FILES); + _trackDesignRepository->Scan(currentLanguage); - _scenarioRepository->Scan(_localisationService->GetCurrentLanguage()); + _preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); + _scenarioRepository->Scan(currentLanguage); }); TitleSequenceManager::Scan(); diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 82f39e674e..320e318bd4 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3855,6 +3855,12 @@ enum : uint16_t STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED = 6629, STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED_TIP = 6630, + STR_LOADING_GENERIC = 6631, + STR_CHECKING_OBJECT_FILES = 6632, + STR_CHECKING_SCENARIO_FILES = 6633, + STR_CHECKING_TRACK_DESIGN_FILES = 6634, + STR_CHECKING_ASSET_PACKS = 6635, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings }; diff --git a/src/openrct2/scenes/preloader/PreloaderScene.cpp b/src/openrct2/scenes/preloader/PreloaderScene.cpp index 969aaf3541..5e38c59803 100644 --- a/src/openrct2/scenes/preloader/PreloaderScene.cpp +++ b/src/openrct2/scenes/preloader/PreloaderScene.cpp @@ -16,6 +16,7 @@ #include "../../audio/audio.h" #include "../../interface/Viewport.h" #include "../../interface/Window.h" +#include "../../localisation/LocalisationService.h" #include "../../localisation/StringIds.h" #include "../../windows/Intent.h" @@ -37,9 +38,7 @@ void PreloaderScene::Load() ContextOpenWindow(WindowClass::MainWindow); WindowResizeGui(ContextGetWidth(), ContextGetHeight()); - auto intent = Intent(WindowClass::NetworkStatus); - intent.PutExtra(INTENT_EXTRA_MESSAGE, std::string{ "Loading..." }); - ContextOpenIntent(&intent); + UpdateCaption(STR_LOADING_GENERIC); LOG_VERBOSE("PreloaderScene::Load() finished"); } @@ -62,6 +61,15 @@ void PreloaderScene::Tick() } } +void PreloaderScene::UpdateCaption(StringId stringId) +{ + LOG_VERBOSE("PreloaderScene::UpdateCaption()"); + + auto intent = Intent(WindowClass::NetworkStatus); + intent.PutExtra(INTENT_EXTRA_MESSAGE, GetContext().GetLocalisationService().GetString(stringId)); + ContextOpenIntent(&intent); +}; + void PreloaderScene::Stop() { Audio::StopAll(); diff --git a/src/openrct2/scenes/preloader/PreloaderScene.h b/src/openrct2/scenes/preloader/PreloaderScene.h index 09324df707..f533e4443e 100644 --- a/src/openrct2/scenes/preloader/PreloaderScene.h +++ b/src/openrct2/scenes/preloader/PreloaderScene.h @@ -23,6 +23,7 @@ namespace OpenRCT2 void Load() override; void Tick() override; void Stop() override; + void UpdateCaption(StringId stringId); void AddJob(const std::function& fn) { _jobs.AddTask(fn); From fe7152fc724f8e904629666cb73ed7248e654d5d Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 24 Apr 2024 23:15:21 +0200 Subject: [PATCH 3/9] Skip viewport render during preloader Reset screen to a nice background colour --- src/openrct2-ui/windows/Main.cpp | 4 ++++ src/openrct2-ui/windows/NetworkStatus.cpp | 1 + src/openrct2/scenes/preloader/PreloaderScene.cpp | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index d99748a713..f13a01bbc8 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -46,6 +46,10 @@ static Widget _mainWidgets[] = { void OnDraw(DrawPixelInfo& dpi) override { + // Skip viewport render during preloader + if (GetContext()->GetActiveScene() == GetContext()->GetPreloaderScene()) + return; + ViewportRender(dpi, viewport, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } }); } diff --git a/src/openrct2-ui/windows/NetworkStatus.cpp b/src/openrct2-ui/windows/NetworkStatus.cpp index 0273474906..7f61a2b4bb 100644 --- a/src/openrct2-ui/windows/NetworkStatus.cpp +++ b/src/openrct2-ui/windows/NetworkStatus.cpp @@ -117,6 +117,7 @@ static Widget window_network_status_widgets[] = { void SetWindowNetworkStatusText(const std::string& text) { _windowNetworkStatusText = text; + Invalidate(); } void SetPassword(char* password) diff --git a/src/openrct2/scenes/preloader/PreloaderScene.cpp b/src/openrct2/scenes/preloader/PreloaderScene.cpp index 5e38c59803..830621ac0f 100644 --- a/src/openrct2/scenes/preloader/PreloaderScene.cpp +++ b/src/openrct2/scenes/preloader/PreloaderScene.cpp @@ -14,6 +14,8 @@ #include "../../GameState.h" #include "../../OpenRCT2.h" #include "../../audio/audio.h" +#include "../../drawing/IDrawingContext.h" +#include "../../drawing/IDrawingEngine.h" #include "../../interface/Viewport.h" #include "../../interface/Window.h" #include "../../localisation/LocalisationService.h" @@ -38,6 +40,11 @@ void PreloaderScene::Load() ContextOpenWindow(WindowClass::MainWindow); WindowResizeGui(ContextGetWidth(), ContextGetHeight()); + // Reset screen + auto* engine = GetContext().GetDrawingEngine(); + auto* drawingContext = engine->GetDrawingContext(); + drawingContext->Clear(*engine->GetDrawingPixelInfo(), PALETTE_INDEX_10); + UpdateCaption(STR_LOADING_GENERIC); LOG_VERBOSE("PreloaderScene::Load() finished"); From 3cda6e367b19a85543b1f85504bbf57004270bdd Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Thu, 25 Apr 2024 23:55:52 +0200 Subject: [PATCH 4/9] Don't use preloader scene when in headless mode to fix replay tests This splits off the initialisation calls to a new InitialiseRepositories function. The SetCompletionScene invocation is moved to the Launch method. When the game is running in headless mode, the preloader is not used. Instead, InitialiseRepositories is called in-thread, and the transition to the 'completion scene' happens immediately after. --- src/openrct2/Context.cpp | 74 +++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 6784bc13d1..ffa967ae87 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -504,31 +504,19 @@ namespace OpenRCT2 ContextInit(); - _preloaderScene->AddJob([&]() { - auto currentLanguage = _localisationService->GetCurrentLanguage(); - - _preloaderScene->UpdateCaption(STR_CHECKING_OBJECT_FILES); - _objectRepository->LoadOrConstruct(currentLanguage); - - if (!gOpenRCT2Headless) - { - _preloaderScene->UpdateCaption(STR_CHECKING_ASSET_PACKS); - _assetPackManager->Scan(); - _assetPackManager->LoadEnabledAssetPacks(); - _assetPackManager->Reload(); - } - - _preloaderScene->UpdateCaption(STR_CHECKING_TRACK_DESIGN_FILES); - _trackDesignRepository->Scan(currentLanguage); - - _preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); - _scenarioRepository->Scan(currentLanguage); - }); - TitleSequenceManager::Scan(); - _preloaderScene->SetCompletionScene(GetTitleScene()); - SetActiveScene(_preloaderScene.get()); + if (!gOpenRCT2Headless) + { + _preloaderScene->AddJob([this]() { InitialiseRepositories(); }); + + // TODO: preload the title scene in another (parallel) job. + SetActiveScene(_preloaderScene.get()); + } + else + { + InitialiseRepositories(); + } #ifdef ENABLE_SCRIPTING _scriptEngine.Initialise(); @@ -539,6 +527,37 @@ namespace OpenRCT2 return true; } + private: + void InitialiseRepositories() + { + if (!_initialised) + { + throw std::runtime_error("Context needs to be initialised first."); + } + + auto currentLanguage = _localisationService->GetCurrentLanguage(); + + _preloaderScene->UpdateCaption(STR_CHECKING_OBJECT_FILES); + _objectRepository->LoadOrConstruct(currentLanguage); + + if (!gOpenRCT2Headless) + { + _preloaderScene->UpdateCaption(STR_CHECKING_ASSET_PACKS); + _assetPackManager->Scan(); + _assetPackManager->LoadEnabledAssetPacks(); + _assetPackManager->Reload(); + } + + _preloaderScene->UpdateCaption(STR_CHECKING_TRACK_DESIGN_FILES); + _trackDesignRepository->Scan(currentLanguage); + + _preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); + _scenarioRepository->Scan(currentLanguage); + + _preloaderScene->UpdateCaption(STR_LOADING_GENERIC); + } + + public: void InitialiseDrawingEngine() final override { assert(_drawingEngine == nullptr); @@ -1020,7 +1039,14 @@ namespace OpenRCT2 } auto* scene = DetermineStartUpScene(); - SetActiveScene(scene); + if (!gOpenRCT2Headless) + { + _preloaderScene->SetCompletionScene(scene); + } + else + { + SetActiveScene(scene); + } if (scene == GetGameScene()) { From 809fe4a51bf97aa4bef45815f42a6c35bac594f7 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 6 May 2024 14:08:35 +0200 Subject: [PATCH 5/9] Initialise scenes only when they are first accessed --- src/openrct2/Context.cpp | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index ffa967ae87..ca72ae76a1 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -177,10 +177,6 @@ namespace OpenRCT2 #ifndef DISABLE_NETWORK , _network(*this) #endif - , _preloaderScene(std::make_unique(*this)) - , _introScene(std::make_unique(*this)) - , _titleScene(std::make_unique(*this)) - , _gameScene(std::make_unique(*this)) , _painter(std::make_unique(uiContext)) { // Can't have more than one context currently. @@ -314,23 +310,41 @@ namespace OpenRCT2 return EXIT_FAILURE; } - IScene* GetPreloaderScene() override + // NB: This takes some liberty in returning PreloaderScene* instead of IScene*. + // PreloaderScene adds some methods to Scene, which are used internally by Context. + PreloaderScene* GetPreloaderScene() override { + if (auto* scene = _preloaderScene.get()) + return scene; + + _preloaderScene = std::make_unique(*this); return _preloaderScene.get(); } IScene* GetIntroScene() override { + if (auto* scene = _introScene.get()) + return scene; + + _introScene = std::make_unique(*this); return _introScene.get(); } IScene* GetTitleScene() override { + if (auto* scene = _titleScene.get()) + return scene; + + _titleScene = std::make_unique(*this); return _titleScene.get(); } IScene* GetGameScene() override { + if (auto* scene = _gameScene.get()) + return scene; + + _gameScene = std::make_unique(*this); return _gameScene.get(); } @@ -508,10 +522,11 @@ namespace OpenRCT2 if (!gOpenRCT2Headless) { - _preloaderScene->AddJob([this]() { InitialiseRepositories(); }); + auto* preloaderScene = GetPreloaderScene(); + preloaderScene->AddJob([this]() { InitialiseRepositories(); }); // TODO: preload the title scene in another (parallel) job. - SetActiveScene(_preloaderScene.get()); + SetActiveScene(preloaderScene); } else { @@ -536,25 +551,26 @@ namespace OpenRCT2 } auto currentLanguage = _localisationService->GetCurrentLanguage(); + auto* preloaderScene = GetPreloaderScene(); - _preloaderScene->UpdateCaption(STR_CHECKING_OBJECT_FILES); + preloaderScene->UpdateCaption(STR_CHECKING_OBJECT_FILES); _objectRepository->LoadOrConstruct(currentLanguage); if (!gOpenRCT2Headless) { - _preloaderScene->UpdateCaption(STR_CHECKING_ASSET_PACKS); + preloaderScene->UpdateCaption(STR_CHECKING_ASSET_PACKS); _assetPackManager->Scan(); _assetPackManager->LoadEnabledAssetPacks(); _assetPackManager->Reload(); } - _preloaderScene->UpdateCaption(STR_CHECKING_TRACK_DESIGN_FILES); + preloaderScene->UpdateCaption(STR_CHECKING_TRACK_DESIGN_FILES); _trackDesignRepository->Scan(currentLanguage); - _preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); + preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); _scenarioRepository->Scan(currentLanguage); - _preloaderScene->UpdateCaption(STR_LOADING_GENERIC); + preloaderScene->UpdateCaption(STR_LOADING_GENERIC); } public: From db73b1fede0c7210478891b51bf123f4ac09f5ef Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 6 May 2024 14:08:49 +0200 Subject: [PATCH 6/9] Move TitleSequenceManager::Scan into preloader as well Add strings for checking and loading title sequence --- data/language/en-GB.txt | 2 ++ src/openrct2/Context.cpp | 10 +++++++--- src/openrct2/localisation/StringIds.h | 2 ++ src/openrct2/scenes/Scene.cpp | 5 +++++ src/openrct2/scenes/Scene.h | 3 +++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 636b35a5b9..84f2fc1520 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3707,6 +3707,8 @@ STR_6632 :Checking object files... STR_6633 :Checking scenario files... STR_6634 :Checking track design files... STR_6635 :Checking asset packs... +STR_6636 :Checking title sequences... +STR_6637 :Loading title sequence... ############# # Scenarios # diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index ca72ae76a1..a47cf8c9dd 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -518,8 +518,6 @@ namespace OpenRCT2 ContextInit(); - TitleSequenceManager::Scan(); - if (!gOpenRCT2Headless) { auto* preloaderScene = GetPreloaderScene(); @@ -570,7 +568,13 @@ namespace OpenRCT2 preloaderScene->UpdateCaption(STR_CHECKING_SCENARIO_FILES); _scenarioRepository->Scan(currentLanguage); - preloaderScene->UpdateCaption(STR_LOADING_GENERIC); + preloaderScene->UpdateCaption(STR_CHECKING_TITLE_SEQUENCES); + TitleSequenceManager::Scan(); + + if (preloaderScene->GetCompletionScene() == GetTitleScene()) + preloaderScene->UpdateCaption(STR_LOADING_TITLE_SEQUENCE); + else + preloaderScene->UpdateCaption(STR_LOADING_GENERIC); } public: diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 320e318bd4..ad8cca6f7a 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3860,6 +3860,8 @@ enum : uint16_t STR_CHECKING_SCENARIO_FILES = 6633, STR_CHECKING_TRACK_DESIGN_FILES = 6634, STR_CHECKING_ASSET_PACKS = 6635, + STR_CHECKING_TITLE_SEQUENCES = 6636, + STR_LOADING_TITLE_SEQUENCE = 6637, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings diff --git a/src/openrct2/scenes/Scene.cpp b/src/openrct2/scenes/Scene.cpp index 6e8316548a..f300c0d02c 100644 --- a/src/openrct2/scenes/Scene.cpp +++ b/src/openrct2/scenes/Scene.cpp @@ -38,6 +38,11 @@ void Scene::FinishScene() } } +IScene* Scene::GetCompletionScene() +{ + return _nextScene; +} + void Scene::SetCompletionScene(IScene* scene) { _nextScene = scene; diff --git a/src/openrct2/scenes/Scene.h b/src/openrct2/scenes/Scene.h index 6e7c5edd12..a082717d26 100644 --- a/src/openrct2/scenes/Scene.h +++ b/src/openrct2/scenes/Scene.h @@ -27,6 +27,8 @@ namespace OpenRCT2 virtual void Load() = 0; virtual void Tick() = 0; virtual void Stop() = 0; + + virtual IScene* GetCompletionScene() = 0; virtual void SetCompletionScene(IScene* scene) = 0; }; @@ -38,6 +40,7 @@ namespace OpenRCT2 GameState_t& GetGameState() override; IContext& GetContext() override; + IScene* GetCompletionScene() override; void SetCompletionScene(IScene* scene) override; protected: From 3e000d550b050d98e6d3719a7e7b31aaf1dc2d16 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 6 May 2024 15:44:07 +0200 Subject: [PATCH 7/9] Prevent NetworkStatusWindow border from flashing on update --- src/openrct2-ui/windows/NetworkStatus.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/openrct2-ui/windows/NetworkStatus.cpp b/src/openrct2-ui/windows/NetworkStatus.cpp index 7f61a2b4bb..6e25fe4af9 100644 --- a/src/openrct2-ui/windows/NetworkStatus.cpp +++ b/src/openrct2-ui/windows/NetworkStatus.cpp @@ -133,8 +133,17 @@ static Widget window_network_status_widgets[] = { WindowBase* NetworkStatusOpen(const std::string& text, close_callback onClose) { - auto window = WindowFocusOrCreate( - WindowClass::NetworkStatus, 420, 90, WF_10 | WF_TRANSPARENT | WF_CENTRE_SCREEN); + NetworkStatusWindow* window; + if ((window = static_cast(WindowFindByClass(WindowClass::NetworkStatus))) != nullptr) + { + WindowBringToFront(*window); + } + else + { + window = WindowCreate( + WindowClass::NetworkStatus, 420, 90, WF_10 | WF_TRANSPARENT | WF_CENTRE_SCREEN); + } + window->SetCloseCallBack(onClose); window->SetWindowNetworkStatusText(text); return window; From 2ff3295587c646a17d87556167710b73506419a4 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 6 May 2024 14:26:00 +0000 Subject: [PATCH 8/9] Report FileIndex index progress to Context Progress is passed on to PreloaderScene and NetworkInfo window from there. --- src/openrct2/Context.cpp | 8 ++++++++ src/openrct2/Context.h | 2 ++ src/openrct2/core/FileIndex.hpp | 2 ++ .../scenes/preloader/PreloaderScene.cpp | 18 ++++++++++++++++-- src/openrct2/scenes/preloader/PreloaderScene.h | 2 ++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index a47cf8c9dd..b22c438b6f 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -643,6 +643,14 @@ namespace OpenRCT2 _drawingEngine = nullptr; } + void SetProgress(size_t currentProgress, size_t totalCount) override + { + if (GetActiveScene() != GetPreloaderScene()) + return; + + GetPreloaderScene()->SetProgress(currentProgress, totalCount); + } + bool LoadParkFromFile(const u8string& path, bool loadTitleScreenOnFail = false, bool asScenario = false) final override { LOG_VERBOSE("Context::LoadParkFromFile(%s)", path.c_str()); diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index 95000ddbd2..4fa8e38c66 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -158,6 +158,8 @@ namespace OpenRCT2 virtual bool Initialise() abstract; virtual void InitialiseDrawingEngine() abstract; virtual void DisposeDrawingEngine() abstract; + virtual void SetProgress(size_t currentProgress, size_t totalCount) abstract; + virtual bool LoadParkFromFile( const u8string& path, bool loadTitleScreenOnFail = false, bool asScenario = false) abstract; virtual bool LoadParkFromStream( diff --git a/src/openrct2/core/FileIndex.hpp b/src/openrct2/core/FileIndex.hpp index 18c9256a8d..442bb92f38 100644 --- a/src/openrct2/core/FileIndex.hpp +++ b/src/openrct2/core/FileIndex.hpp @@ -9,6 +9,7 @@ #pragma once +#include "../Context.h" #include "../common.h" #include "Console.hpp" #include "DataSerialiser.h" @@ -211,6 +212,7 @@ private: auto reportProgress = [&]() { const size_t completed = processed; Console::WriteFormat("File %5zu of %zu, done %3d%%\r", completed, totalCount, completed * 100 / totalCount); + OpenRCT2::GetContext()->SetProgress(completed, totalCount); }; for (size_t rangeStart = 0; rangeStart < totalCount; rangeStart += stepSize) diff --git a/src/openrct2/scenes/preloader/PreloaderScene.cpp b/src/openrct2/scenes/preloader/PreloaderScene.cpp index 830621ac0f..b4505f0fbb 100644 --- a/src/openrct2/scenes/preloader/PreloaderScene.cpp +++ b/src/openrct2/scenes/preloader/PreloaderScene.cpp @@ -22,11 +22,14 @@ #include "../../localisation/StringIds.h" #include "../../windows/Intent.h" +#include + using namespace OpenRCT2; PreloaderScene::PreloaderScene(IContext& context) : Scene(context) , _jobs(1) + , _captionId(STR_LOADING_GENERIC) { } @@ -45,7 +48,7 @@ void PreloaderScene::Load() auto* drawingContext = engine->GetDrawingContext(); drawingContext->Clear(*engine->GetDrawingPixelInfo(), PALETTE_INDEX_10); - UpdateCaption(STR_LOADING_GENERIC); + UpdateCaption(_captionId); LOG_VERBOSE("PreloaderScene::Load() finished"); } @@ -70,13 +73,24 @@ void PreloaderScene::Tick() void PreloaderScene::UpdateCaption(StringId stringId) { - LOG_VERBOSE("PreloaderScene::UpdateCaption()"); + _captionId = stringId; auto intent = Intent(WindowClass::NetworkStatus); intent.PutExtra(INTENT_EXTRA_MESSAGE, GetContext().GetLocalisationService().GetString(stringId)); ContextOpenIntent(&intent); }; +void PreloaderScene::SetProgress(size_t currentProgress, size_t totalCount) +{ + std::stringstream caption; + caption << GetContext().GetLocalisationService().GetString(_captionId); + caption << " (" << currentProgress << " / " << totalCount << ")"; + + auto intent = Intent(WindowClass::NetworkStatus); + intent.PutExtra(INTENT_EXTRA_MESSAGE, caption.str()); + ContextOpenIntent(&intent); +} + void PreloaderScene::Stop() { Audio::StopAll(); diff --git a/src/openrct2/scenes/preloader/PreloaderScene.h b/src/openrct2/scenes/preloader/PreloaderScene.h index f533e4443e..eaf7eafcd7 100644 --- a/src/openrct2/scenes/preloader/PreloaderScene.h +++ b/src/openrct2/scenes/preloader/PreloaderScene.h @@ -24,6 +24,7 @@ namespace OpenRCT2 void Tick() override; void Stop() override; void UpdateCaption(StringId stringId); + void SetProgress(size_t currentProgress, size_t totalCount); void AddJob(const std::function& fn) { _jobs.AddTask(fn); @@ -31,5 +32,6 @@ namespace OpenRCT2 private: JobPool _jobs; + StringId _captionId; }; } // namespace OpenRCT2 From f51404d29d1bf6b91bc10625167491756c8338e7 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 7 May 2024 11:20:56 +0200 Subject: [PATCH 9/9] Amend changelog --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 38800cab15..d7b8eaf4b0 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#622] Add option to align the top toolbar buttons horizontally centred (off by default). - Feature: [#21714] [Plugin] Costume assignment is now tailored to each staff type. +- Feature: [#21893] On launch, the game now indicates what system is being initialised. - Feature: [#21913] [Plugin] Allow precise and safe control of peep animations. - Improved: [#21981] Rendering performance of the map window has been improved considerably. - Improved: [#21981] The map window now defaults to showing as much of the map as fits the screen.