This commit is contained in:
Aaron van Geffen 2024-05-09 06:28:02 -03:00 committed by GitHub
commit b62bf01a83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 301 additions and 38 deletions

View File

@ -3699,6 +3699,13 @@ STR_6624 :Tile Inspector: Sort elements
STR_6625 :Invalid colour
STR_6626 :Animation is backwards
STR_6627 :Track speed too high!
STR_6628 :Loading...
STR_6629 :Checking object files...
STR_6630 :Checking scenario files...
STR_6631 :Checking track design files...
STR_6632 :Checking asset packs...
STR_6633 :Checking title sequences...
STR_6634 :Loading title sequence...
#############
# Scenarios #

View File

@ -1,6 +1,7 @@
0.4.12 (in development)
------------------------------------------------------------------------
- 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.

View File

@ -47,6 +47,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 } });
}

View File

@ -117,6 +117,7 @@ static Widget window_network_status_widgets[] = {
void SetWindowNetworkStatusText(const std::string& text)
{
_windowNetworkStatusText = text;
Invalidate();
}
void SetPassword(char* password)
@ -132,8 +133,17 @@ static Widget window_network_status_widgets[] = {
WindowBase* NetworkStatusOpen(const std::string& text, close_callback onClose)
{
auto window = WindowFocusOrCreate<NetworkStatusWindow>(
WindowClass::NetworkStatus, 420, 90, WF_10 | WF_TRANSPARENT | WF_CENTRE_SCREEN);
NetworkStatusWindow* window;
if ((window = static_cast<NetworkStatusWindow*>(WindowFindByClass(WindowClass::NetworkStatus))) != nullptr)
{
WindowBringToFront(*window);
}
else
{
window = WindowCreate<NetworkStatusWindow>(
WindowClass::NetworkStatus, 420, 90, WF_10 | WF_TRANSPARENT | WF_CENTRE_SCREEN);
}
window->SetCloseCallBack(onClose);
window->SetWindowNetworkStatusText(text);
return window;

View File

@ -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> _preloaderScene;
std::unique_ptr<IntroScene> _introScene;
std::unique_ptr<TitleScene> _titleScene;
std::unique_ptr<GameScene> _gameScene;
@ -175,9 +177,6 @@ namespace OpenRCT2
#ifndef DISABLE_NETWORK
, _network(*this)
#endif
, _introScene(std::make_unique<IntroScene>(*this))
, _titleScene(std::make_unique<TitleScene>(*this))
, _gameScene(std::make_unique<GameScene>(*this))
, _painter(std::make_unique<Painter>(uiContext))
{
// Can't have more than one context currently.
@ -311,24 +310,39 @@ namespace OpenRCT2
return EXIT_FAILURE;
}
IScene* GetLoadingScene() override
PreloaderScene* GetPreloaderScene() override
{
// TODO: Implement me.
return nullptr;
if (auto* scene = _preloaderScene.get())
return scene;
_preloaderScene = std::make_unique<PreloaderScene>(*this);
return _preloaderScene.get();
}
IScene* GetIntroScene() override
{
if (auto* scene = _introScene.get())
return scene;
_introScene = std::make_unique<IntroScene>(*this);
return _introScene.get();
}
IScene* GetTitleScene() override
{
if (auto* scene = _titleScene.get())
return scene;
_titleScene = std::make_unique<TitleScene>(*this);
return _titleScene.get();
}
IScene* GetGameScene() override
{
if (auto* scene = _gameScene.get())
return scene;
_gameScene = std::make_unique<GameScene>(*this);
return _gameScene.get();
}
@ -376,7 +390,7 @@ namespace OpenRCT2
ContextOpenWindow(WindowClass::SavePrompt);
}
bool Initialise() final override
bool Initialise() override
{
if (_initialised)
{
@ -477,26 +491,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 +514,20 @@ namespace OpenRCT2
InputResetPlaceObjModifier();
ViewportInitAll();
gameStateInitAll(GetGameState(), DEFAULT_MAP_SIZE);
ContextInit();
if (!gOpenRCT2Headless)
{
auto* preloaderScene = GetPreloaderScene();
preloaderScene->AddJob([this]() { InitialiseRepositories(); });
// TODO: preload the title scene in another (parallel) job.
SetActiveScene(preloaderScene);
}
else
{
InitialiseRepositories();
}
#ifdef ENABLE_SCRIPTING
_scriptEngine.Initialise();
@ -531,7 +538,43 @@ namespace OpenRCT2
return true;
}
void InitialiseDrawingEngine() final override
void InitialiseRepositories() override
{
if (!_initialised)
{
throw std::runtime_error("Context needs to be initialised first.");
}
auto currentLanguage = _localisationService->GetCurrentLanguage();
auto* preloaderScene = GetPreloaderScene();
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_CHECKING_TITLE_SEQUENCES);
TitleSequenceManager::Scan();
if (preloaderScene->GetCompletionScene() == GetTitleScene())
preloaderScene->UpdateCaption(STR_LOADING_TITLE_SEQUENCE);
else
preloaderScene->UpdateCaption(STR_LOADING_GENERIC);
}
void InitialiseDrawingEngine() override
{
assert(_drawingEngine == nullptr);
@ -591,12 +634,20 @@ namespace OpenRCT2
WindowCheckAllValidZoom();
}
void DisposeDrawingEngine() final override
void SetProgress(size_t currentProgress, size_t totalCount) override
{
if (GetActiveScene() != GetPreloaderScene())
return;
GetPreloaderScene()->SetProgress(currentProgress, totalCount);
}
void DisposeDrawingEngine() override
{
_drawingEngine = nullptr;
}
bool LoadParkFromFile(const u8string& path, bool loadTitleScreenOnFail = false, bool asScenario = false) final override
bool LoadParkFromFile(const u8string& path, bool loadTitleScreenOnFail = false, bool asScenario = false) override
{
LOG_VERBOSE("Context::LoadParkFromFile(%s)", path.c_str());
@ -648,8 +699,7 @@ namespace OpenRCT2
}
bool LoadParkFromStream(
IStream* stream, const std::string& path, bool loadTitleScreenFirstOnFail = false,
bool asScenario = false) final override
IStream* stream, const std::string& path, bool loadTitleScreenFirstOnFail = false, bool asScenario = false) override
{
try
{
@ -1011,7 +1061,14 @@ namespace OpenRCT2
}
auto* scene = DetermineStartUpScene();
SetActiveScene(scene);
if (!gOpenRCT2Headless)
{
_preloaderScene->SetCompletionScene(scene);
}
else
{
SetActiveScene(scene);
}
if (scene == GetGameScene())
{

View File

@ -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;
@ -156,8 +156,11 @@ namespace OpenRCT2
virtual int32_t RunOpenRCT2(int argc, const char** argv) abstract;
virtual bool Initialise() abstract;
virtual void InitialiseRepositories() 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(

View File

@ -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)

View File

@ -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);

View File

@ -46,6 +46,7 @@ public:
void AddTask(std::function<void()> workFn, std::function<void()> completionFn = nullptr);
void Join(std::function<void()> reportFn = nullptr);
size_t CountPending();
size_t CountProcessing();
private:
void ProcessQueue();

View File

@ -515,8 +515,9 @@
<ClInclude Include="scenario\ScenarioRepository.h" />
<ClInclude Include="scenario\ScenarioSources.h" />
<ClInclude Include="scenes\Scene.h" />
<ClInclude Include="scenes\intro\IntroScene.h" />
<ClInclude Include="scenes\game\GameScene.h" />
<ClInclude Include="scenes\intro\IntroScene.h" />
<ClInclude Include="scenes\preloader\PreloaderScene.h" />
<ClInclude Include="scenes\title\Command\End.h" />
<ClInclude Include="scenes\title\Command\FollowEntity.h" />
<ClInclude Include="scenes\title\Command\LoadPark.h" />
@ -1007,6 +1008,7 @@
<ClCompile Include="scenes\Scene.cpp" />
<ClCompile Include="scenes\game\GameScene.cpp" />
<ClCompile Include="scenes\intro\IntroScene.cpp" />
<ClCompile Include="scenes\preloader\PreloaderScene.cpp" />
<ClCompile Include="scenes\title\Command\End.cpp" />
<ClCompile Include="scenes\title\Command\FollowEntity.cpp" />
<ClCompile Include="scenes\title\Command\LoadPark.cpp" />

View File

@ -4047,6 +4047,14 @@ enum : uint16_t
STR_SPEED_TOO_HIGH = 6627,
STR_LOADING_GENERIC = 6628,
STR_CHECKING_OBJECT_FILES = 6629,
STR_CHECKING_SCENARIO_FILES = 6630,
STR_CHECKING_TRACK_DESIGN_FILES = 6631,
STR_CHECKING_ASSET_PACKS = 6632,
STR_CHECKING_TITLE_SEQUENCES = 6633,
STR_LOADING_TITLE_SEQUENCE = 6634,
// 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
};

View File

@ -28,3 +28,22 @@ GameState_t& Scene::GetGameState()
{
return OpenRCT2::GetGameState();
}
void Scene::FinishScene()
{
if (_nextScene != nullptr)
{
_context.SetActiveScene(_nextScene);
_nextScene = nullptr;
}
}
IScene* Scene::GetCompletionScene()
{
return _nextScene;
}
void Scene::SetCompletionScene(IScene* scene)
{
_nextScene = scene;
}

View File

@ -27,6 +27,9 @@ namespace OpenRCT2
virtual void Load() = 0;
virtual void Tick() = 0;
virtual void Stop() = 0;
virtual IScene* GetCompletionScene() = 0;
virtual void SetCompletionScene(IScene* scene) = 0;
};
class Scene : public IScene
@ -37,8 +40,15 @@ namespace OpenRCT2
GameState_t& GetGameState() override;
IContext& GetContext() override;
IScene* GetCompletionScene() override;
void SetCompletionScene(IScene* scene) override;
protected:
void FinishScene();
protected:
IContext& _context;
IScene* _nextScene = nullptr;
};
} // namespace OpenRCT2

View File

@ -0,0 +1,95 @@
/*****************************************************************************
* 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 "../../drawing/IDrawingContext.h"
#include "../../drawing/IDrawingEngine.h"
#include "../../interface/Viewport.h"
#include "../../interface/Window.h"
#include "../../localisation/LocalisationService.h"
#include "../../paint/Painter.h"
#include "../../windows/Intent.h"
#include <sstream>
using namespace OpenRCT2;
PreloaderScene::PreloaderScene(IContext& context)
: Scene(context)
, _jobs(1)
, _captionId(STR_LOADING_GENERIC)
{
}
void PreloaderScene::Load()
{
LOG_VERBOSE("PreloaderScene::Load()");
gScreenFlags = SCREEN_FLAGS_PLAYING;
gameStateInitAll(GetGameState(), DEFAULT_MAP_SIZE);
ViewportInitAll();
ContextOpenWindow(WindowClass::MainWindow);
WindowResizeGui(ContextGetWidth(), ContextGetHeight());
// Reset screen
auto* engine = GetContext().GetDrawingEngine();
auto* drawingContext = engine->GetDrawingContext();
drawingContext->Clear(*engine->GetDrawingPixelInfo(), PALETTE_INDEX_10);
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::UpdateCaption(StringId stringId)
{
_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();
}

View File

@ -0,0 +1,38 @@
/*****************************************************************************
* 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 "../../common.h"
#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 UpdateCaption(StringId stringId);
void SetProgress(size_t currentProgress, size_t totalCount);
void AddJob(const std::function<void()>& fn)
{
_jobs.AddTask(fn);
}
private:
JobPool _jobs;
StringId _captionId;
};
} // namespace OpenRCT2