Merge pull request #7431 from IntelOrca/refactor/use-shared-ptr-1

Use shared_ptr for long-life objects
This commit is contained in:
Ted John 2018-05-13 00:19:43 +01:00 committed by GitHub
commit bece5e5429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 708 additions and 449 deletions

View File

@ -31,7 +31,8 @@
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
"${workspaceRoot}",
"${workspaceRoot}/src"
],
"defines": [],
"intelliSenseMode": "clang-x64",

View File

@ -42,6 +42,10 @@
9346F9DB208A191900C77D91 /* GuestPathfinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9346F9D7208A191900C77D91 /* GuestPathfinding.cpp */; };
9346F9DC208A191900C77D91 /* GuestPathfinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9346F9D7208A191900C77D91 /* GuestPathfinding.cpp */; };
9346F9DD208A191900C77D91 /* GuestPathfinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9346F9D7208A191900C77D91 /* GuestPathfinding.cpp */; };
933F2CB720935653001B33FD /* LocalisationService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 933F2CB620935653001B33FD /* LocalisationService.cpp */; };
933F2CB820935653001B33FD /* LocalisationService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 933F2CB620935653001B33FD /* LocalisationService.cpp */; };
933F2CB920935653001B33FD /* LocalisationService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 933F2CB620935653001B33FD /* LocalisationService.cpp */; };
933F2CBB20935668001B33FD /* LocalisationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 933F2CBA20935668001B33FD /* LocalisationService.h */; };
C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */; };
C61ADB211FB7DC060024F2EF /* Scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB201FB7DC060024F2EF /* Scenery.cpp */; };
C61ADB231FBBCB8B0024F2EF /* GameBottomToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */; };
@ -645,7 +649,6 @@
4C7B53BA1FFF935B00A52E21 /* user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user.h; sourceTree = "<group>"; };
4C7B53BB1FFF935B00A52E21 /* UTF8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UTF8.cpp; sourceTree = "<group>"; };
4C7B53C61FFF94F900A52E21 /* ConversionTables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionTables.cpp; sourceTree = "<group>"; };
4C7B53C71FFF94F900A52E21 /* ConversionTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionTables.h; sourceTree = "<group>"; };
4C7B53C91FFF991000A52E21 /* Language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Language.h; sourceTree = "<group>"; };
4C7B53CB1FFF995100A52E21 /* Font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Font.h; sourceTree = "<group>"; };
4C7B53CD200029CE00A52E21 /* Line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Line.cpp; sourceTree = "<group>"; };
@ -864,6 +867,8 @@
9308D9FD209908090079EE96 /* Surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Surface.h; sourceTree = "<group>"; };
9346F9D6208A191900C77D91 /* Guest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Guest.cpp; sourceTree = "<group>"; };
9346F9D7208A191900C77D91 /* GuestPathfinding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GuestPathfinding.cpp; sourceTree = "<group>"; };
933F2CB620935653001B33FD /* LocalisationService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalisationService.cpp; sourceTree = "<group>"; };
933F2CBA20935668001B33FD /* LocalisationService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalisationService.h; sourceTree = "<group>"; };
C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TopToolbar.cpp; sourceTree = "<group>"; };
C61ADB201FB7DC060024F2EF /* Scenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scenery.cpp; sourceTree = "<group>"; };
C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameBottomToolbar.cpp; sourceTree = "<group>"; };
@ -1991,7 +1996,6 @@
isa = PBXGroup;
children = (
4C7B53C61FFF94F900A52E21 /* ConversionTables.cpp */,
4C7B53C71FFF94F900A52E21 /* ConversionTables.h */,
4C7B53AA1FFF935B00A52E21 /* Convert.cpp */,
4C7B53AB1FFF935B00A52E21 /* Currency.cpp */,
4C7B53AC1FFF935B00A52E21 /* Currency.h */,
@ -2001,6 +2005,8 @@
4C7B53B01FFF935B00A52E21 /* FormatCodes.h */,
4C7B53B11FFF935B00A52E21 /* Language.cpp */,
4C7B53C91FFF991000A52E21 /* Language.h */,
933F2CB620935653001B33FD /* LocalisationService.cpp */,
933F2CBA20935668001B33FD /* LocalisationService.h */,
4C7B53B31FFF935B00A52E21 /* LanguagePack.cpp */,
4C7B53B41FFF935B00A52E21 /* LanguagePack.h */,
4C7B53B51FFF935B00A52E21 /* Localisation.cpp */,
@ -2716,6 +2722,7 @@
C6352B851F477022006CCEE3 /* DataSerialiserTraits.h in Headers */,
C67B28192002D7F200109C93 /* Window_internal.h in Headers */,
C6352B971F477032006CCEE3 /* SetParkEntranceFeeAction.hpp in Headers */,
933F2CBB20935668001B33FD /* LocalisationService.h in Headers */,
C6352B861F477022006CCEE3 /* Endianness.h in Headers */,
C6352B941F477032006CCEE3 /* PlaceParkEntranceAction.hpp in Headers */,
C6352B911F477032006CCEE3 /* GameAction.h in Headers */,
@ -3021,6 +3028,7 @@
C685E5191F8907850090598F /* NewRide.cpp in Sources */,
9346F9DB208A191900C77D91 /* GuestPathfinding.cpp in Sources */,
C654DF361F69C0430040F43D /* Player.cpp in Sources */,
933F2CB720935653001B33FD /* LocalisationService.cpp in Sources */,
F76C88791EC5324E00FA49E2 /* AudioContext.cpp in Sources */,
C666EE7A1F37ACB10061AA04 /* Themes.cpp in Sources */,
C666EE7F1F37ACB10061AA04 /* Viewport.cpp in Sources */,
@ -3174,6 +3182,7 @@
F76C85C01EC4E88300FA49E2 /* UriHandler.cpp in Sources */,
C688786220289A0A0084B384 /* MapGen.cpp in Sources */,
C68878A820289B2A0084B384 /* NewsItem.cpp in Sources */,
933F2CB820935653001B33FD /* LocalisationService.cpp in Sources */,
F76C85C41EC4E88300FA49E2 /* Config.cpp in Sources */,
C688789120289B140084B384 /* Console.cpp in Sources */,
C688792920289B9B0084B384 /* Chairlift.cpp in Sources */,
@ -3436,6 +3445,7 @@
9346F9DA208A191900C77D91 /* Guest.cpp in Sources */,
F7D7749E1EC6713200BE6EBC /* Cli.cpp in Sources */,
9308DA03209908090079EE96 /* Surface.cpp in Sources */,
933F2CB920935653001B33FD /* LocalisationService.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -62,10 +62,10 @@
<!-- 3rd party libraries / dependencies -->
<PropertyGroup>
<DependenciesCheckFile>$(RootDir).dependencies</DependenciesCheckFile>
<LibsUrl Condition="'$(Platform)'=='Win32'">https://github.com/OpenRCT2/Dependencies/releases/download/v16/openrct2-libs-v16-x86-windows-static-winssl.zip</LibsUrl>
<LibsSha1 Condition="'$(Platform)'=='Win32'">827d86c1571bb73504b23929746b20d8094aae40</LibsSha1>
<LibsUrl Condition="'$(Platform)'=='x64'">https://github.com/OpenRCT2/Dependencies/releases/download/v16/openrct2-libs-v16-x64-windows-static-winssl.zip</LibsUrl>
<LibsSha1 Condition="'$(Platform)'=='x64'">5904b7e0562ace419b7c87d618e5ad00ba664b36</LibsSha1>
<LibsUrl Condition="'$(Platform)'=='Win32'">https://github.com/OpenRCT2/Dependencies/releases/download/v17/openrct2-libs-v17-x86-windows-static-winssl.zip</LibsUrl>
<LibsSha1 Condition="'$(Platform)'=='Win32'">4f9fb5feebe4a4ed461b2a545b2fd1c91ef6527b</LibsSha1>
<LibsUrl Condition="'$(Platform)'=='x64'">https://github.com/OpenRCT2/Dependencies/releases/download/v17/openrct2-libs-v17-x64-windows-static-winssl.zip</LibsUrl>
<LibsSha1 Condition="'$(Platform)'=='x64'">5aab386f9eeaad102b330fcddea2b4cc9e3c7067</LibsSha1>
<GtestVersion>1.8.0</GtestVersion>
<GtestUrl>https://github.com/google/googletest/archive/release-1.8.0.zip</GtestUrl>
<GtestSha1>667f873ab7a4d246062565fad32fb6d8e203ee73</GtestSha1>

View File

@ -99,7 +99,7 @@ if [[ "$(uname)" == "Darwin" ]]; then
elif [[ $(uname) == "Linux" ]]; then
# Clone discord-rpc for Discord's Rich Presence support
# Use tagged release to prevent upstream changes from breaking our code
git clone https://github.com/discordapp/discord-rpc -b v3.2.0
git clone https://github.com/IntelOrca/discord-rpc -b fix/134-iothreadholder
# Use rapidjson with a hack for GCC 8, while awaiting a fix upstream:
# https://github.com/Tencent/rapidjson/issues/1205
git clone https://github.com/janisozaur/rapidjson discord-rpc/thirdparty/rapidjson -b patch-1

View File

@ -36,7 +36,6 @@ int main(int argc, const char * * argv)
// Run OpenRCT2 with a plain context
auto context = CreateContext();
context->RunOpenRCT2(argc, argv);
delete context;
}
return gExitCode;
}

View File

@ -29,6 +29,12 @@ using namespace OpenRCT2;
using namespace OpenRCT2::Audio;
using namespace OpenRCT2::Ui;
template<typename T>
static std::shared_ptr<T> to_shared(std::unique_ptr<T>&& src)
{
return std::shared_ptr<T>(std::move(src));
}
/**
* Main entry point for non-Windows systems. Windows instead uses its own DLL proxy.
*/
@ -47,21 +53,16 @@ int main(int argc, const char * * argv)
// Run OpenRCT2 with a plain context
auto context = CreateContext();
context->RunOpenRCT2(argc, argv);
delete context;
}
else
{
// Run OpenRCT2 with a UI context
auto env = CreatePlatformEnvironment();
auto audioContext = CreateAudioContext();
auto uiContext = CreateUiContext(env);
auto env = to_shared(CreatePlatformEnvironment());
auto audioContext = to_shared(CreateAudioContext());
auto uiContext = to_shared(CreateUiContext(env));
auto context = CreateContext(env, audioContext, uiContext);
context->RunOpenRCT2(argc, argv);
delete context;
delete uiContext;
delete audioContext;
}
}
return gExitCode;

View File

@ -374,7 +374,7 @@ namespace OpenRCT2::Ui
static void ThrowMissingDialogApp()
{
IUiContext * uiContext = GetContext()->GetUiContext();
auto uiContext = GetContext()->GetUiContext();
std::string dialogMissingWarning = language_get_string(STR_MISSING_DIALOG_APPLICATION_ERROR);
uiContext->ShowMessageBox(dialogMissingWarning);
throw std::runtime_error(dialogMissingWarning);

View File

@ -34,7 +34,7 @@
#include <openrct2/ui/WindowManager.h>
#include <openrct2/Version.h>
#include "CursorRepository.h"
#include "drawing/engines/DrawingEngines.h"
#include "drawing/engines/DrawingEngineFactory.hpp"
#include "input/KeyboardShortcuts.h"
#include "SDLException.h"
#include "TextComposition.h"
@ -94,7 +94,7 @@ private:
public:
InGameConsole& GetInGameConsole() { return _inGameConsole; }
explicit UiContext(IPlatformEnvironment * env)
explicit UiContext(const std::shared_ptr<IPlatformEnvironment>& env)
: _platformUiContext(CreatePlatformUiContext()),
_windowManager(CreateWindowManager()),
_keyboardShortcuts(env)
@ -261,20 +261,9 @@ public:
}
// Drawing
IDrawingEngine * CreateDrawingEngine(DRAWING_ENGINE_TYPE type) override
std::shared_ptr<Drawing::IDrawingEngineFactory> GetDrawingEngineFactory() override
{
switch ((sint32)type) {
case DRAWING_ENGINE_SOFTWARE:
return CreateSoftwareDrawingEngine(this);
case DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY:
return CreateHardwareDisplayDrawingEngine(this);
#ifndef DISABLE_OPENGL
case DRAWING_ENGINE_OPENGL:
return CreateOpenGLDrawingEngine(this);
#endif
default:
return nullptr;
}
return std::make_shared<DrawingEngineFactory>();
}
// Text input
@ -814,13 +803,13 @@ private:
}
};
IUiContext * OpenRCT2::Ui::CreateUiContext(IPlatformEnvironment * env)
std::unique_ptr<IUiContext> OpenRCT2::Ui::CreateUiContext(const std::shared_ptr<IPlatformEnvironment>& env)
{
return new UiContext(env);
return std::make_unique<UiContext>(env);
}
InGameConsole& OpenRCT2::Ui::GetInGameConsole()
{
auto uiContext = static_cast<UiContext *>(GetContext()->GetUiContext());
auto uiContext = std::static_pointer_cast<UiContext>(GetContext()->GetUiContext());
return uiContext->GetInGameConsole();
}

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <string>
#include <openrct2/common.h>
@ -43,7 +44,7 @@ namespace OpenRCT2
virtual std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) abstract;
};
IUiContext * CreateUiContext(IPlatformEnvironment * env);
std::unique_ptr<IUiContext> CreateUiContext(const std::shared_ptr<IPlatformEnvironment>& env);
IPlatformUiContext * CreatePlatformUiContext();
InGameConsole& GetInGameConsole();

View File

@ -94,8 +94,8 @@ namespace OpenRCT2::Audio
void StopVehicleSounds() override { }
};
IAudioContext * CreateAudioContext()
std::unique_ptr<IAudioContext> CreateAudioContext()
{
return new AudioContext();
return std::make_unique<AudioContext>();
}
} // namespace OpenRCT2::Audio

View File

@ -1,6 +1,7 @@
#pragma once
#include <memory>
#include <string>
#include <openrct2/common.h>
#include <openrct2/audio/AudioChannel.h>
@ -69,5 +70,6 @@ namespace OpenRCT2::Audio
IAudioMixer * Create();
}
IAudioContext * CreateAudioContext();
std::unique_ptr<IAudioContext> CreateAudioContext();
} // namespace OpenRCT2::Audio

View File

@ -0,0 +1,57 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include <memory>
#include <openrct2/common.h>
#include <openrct2/drawing/IDrawingEngine.h>
namespace OpenRCT2
{
namespace Ui
{
using namespace OpenRCT2::Drawing;
interface IUiContext;
std::unique_ptr<IDrawingEngine> CreateSoftwareDrawingEngine(const std::shared_ptr<IUiContext>& uiContext);
std::unique_ptr<IDrawingEngine> CreateHardwareDisplayDrawingEngine(const std::shared_ptr<IUiContext>& uiContext);
#ifndef DISABLE_OPENGL
std::unique_ptr<IDrawingEngine> CreateOpenGLDrawingEngine(const std::shared_ptr<IUiContext>& uiContext);
#endif
class DrawingEngineFactory final : public IDrawingEngineFactory
{
public:
std::unique_ptr<IDrawingEngine> Create(DRAWING_ENGINE_TYPE type, const std::shared_ptr<IUiContext>& uiContext) override
{
switch ((sint32)type) {
case DRAWING_ENGINE_SOFTWARE:
return CreateSoftwareDrawingEngine(uiContext);
case DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY:
return CreateHardwareDisplayDrawingEngine(uiContext);
#ifndef DISABLE_OPENGL
case DRAWING_ENGINE_OPENGL:
return CreateOpenGLDrawingEngine(uiContext);
#endif
default:
return nullptr;
}
}
};
}
}

View File

@ -1,38 +0,0 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include <openrct2/common.h>
namespace OpenRCT2
{
namespace Drawing
{
interface IDrawingEngine;
}
namespace Ui
{
interface IUiContext;
Drawing::IDrawingEngine * CreateSoftwareDrawingEngine(IUiContext * uiContext);
Drawing::IDrawingEngine * CreateHardwareDisplayDrawingEngine(IUiContext * uiContext);
#ifndef DISABLE_OPENGL
Drawing::IDrawingEngine * CreateOpenGLDrawingEngine(IUiContext * uiContext);
#endif
}
}

View File

@ -22,7 +22,7 @@
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/X8DrawingEngine.h>
#include <openrct2/ui/UiContext.h>
#include "DrawingEngines.h"
#include "DrawingEngineFactory.hpp"
#include <openrct2/drawing/LightFX.h>
#include <openrct2/Game.h>
@ -37,7 +37,7 @@ class HardwareDisplayDrawingEngine final : public X8DrawingEngine
private:
constexpr static uint32 DIRTY_VISUAL_TIME = 32;
IUiContext * const _uiContext;
std::shared_ptr<IUiContext> const _uiContext;
SDL_Window * _window = nullptr;
SDL_Renderer * _sdlRenderer = nullptr;
SDL_Texture * _screenTexture = nullptr;
@ -60,7 +60,7 @@ private:
bool smoothNN = false;
public:
explicit HardwareDisplayDrawingEngine(IUiContext * uiContext)
explicit HardwareDisplayDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
: X8DrawingEngine(uiContext),
_uiContext(uiContext)
{
@ -415,7 +415,7 @@ private:
}
};
IDrawingEngine * OpenRCT2::Ui::CreateHardwareDisplayDrawingEngine(IUiContext * uiContext)
std::unique_ptr<IDrawingEngine> OpenRCT2::Ui::CreateHardwareDisplayDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
{
return new HardwareDisplayDrawingEngine(uiContext);
return std::make_unique<HardwareDisplayDrawingEngine>(uiContext);
}

View File

@ -23,7 +23,7 @@
#include <openrct2/drawing/X8DrawingEngine.h>
#include <openrct2/Game.h>
#include <openrct2/ui/UiContext.h>
#include "DrawingEngines.h"
#include "DrawingEngineFactory.hpp"
using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;
@ -32,14 +32,14 @@ using namespace OpenRCT2::Ui;
class SoftwareDrawingEngine final : public X8DrawingEngine
{
private:
IUiContext * const _uiContext;
std::shared_ptr<IUiContext> const _uiContext;
SDL_Window * _window = nullptr;
SDL_Surface * _surface = nullptr;
SDL_Surface * _RGBASurface = nullptr;
SDL_Palette * _palette = nullptr;
public:
explicit SoftwareDrawingEngine(IUiContext * uiContext)
explicit SoftwareDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
: X8DrawingEngine(uiContext),
_uiContext(uiContext)
{
@ -163,7 +163,7 @@ private:
}
};
IDrawingEngine * OpenRCT2::Ui::CreateSoftwareDrawingEngine(IUiContext * uiContext)
std::unique_ptr<IDrawingEngine> OpenRCT2::Ui::CreateSoftwareDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
{
return new SoftwareDrawingEngine(uiContext);
return std::make_unique<SoftwareDrawingEngine>(uiContext);
}

View File

@ -31,7 +31,7 @@
#include <openrct2/Intro.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/ui/UiContext.h>
#include "../DrawingEngines.h"
#include "../DrawingEngineFactory.hpp"
#include "ApplyPaletteShader.h"
#include "DrawCommands.h"
#include "DrawLineShader.h"
@ -121,7 +121,7 @@ public:
class OpenGLDrawingEngine : public IDrawingEngine
{
private:
IUiContext * const _uiContext = nullptr;
std::shared_ptr<IUiContext> const _uiContext;
SDL_Window * _window = nullptr;
SDL_GLContext _context = nullptr;
@ -144,7 +144,7 @@ public:
SDL_Color Palette[256];
vec4 GLPalette[256];
explicit OpenGLDrawingEngine(IUiContext * uiContext)
explicit OpenGLDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
: _uiContext(uiContext)
{
_window = (SDL_Window *)_uiContext->GetWindow();
@ -419,9 +419,9 @@ private:
}
};
IDrawingEngine * OpenRCT2::Ui::CreateOpenGLDrawingEngine(IUiContext * uiContext)
std::unique_ptr<IDrawingEngine> OpenRCT2::Ui::CreateOpenGLDrawingEngine(const std::shared_ptr<IUiContext>& uiContext)
{
return new OpenGLDrawingEngine(uiContext);
return std::make_unique<OpenGLDrawingEngine>(uiContext);
}
OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine)

View File

@ -32,12 +32,17 @@ using namespace OpenRCT2::Input;
// Remove when the C calls are removed
static KeyboardShortcuts * _instance;
KeyboardShortcuts::KeyboardShortcuts(IPlatformEnvironment * env)
KeyboardShortcuts::KeyboardShortcuts(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env)
{
_instance = this;
}
KeyboardShortcuts::~KeyboardShortcuts()
{
_instance = nullptr;
}
void KeyboardShortcuts::Reset()
{
for (size_t i = 0; i < SHORTCUT_COUNT; i++)

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <openrct2/common.h>
#define SHIFT 0x100
@ -119,11 +120,12 @@ namespace OpenRCT2
constexpr static sint32 CURRENT_FILE_VERSION = 1;
static const uint16 DefaultKeys[SHORTCUT_COUNT];
IPlatformEnvironment * const _env;
std::shared_ptr<IPlatformEnvironment> const _env;
uint16 _keys[SHORTCUT_COUNT];
public:
KeyboardShortcuts(IPlatformEnvironment * env);
KeyboardShortcuts(const std::shared_ptr<IPlatformEnvironment>& env);
~KeyboardShortcuts();
void Reset();
bool Load();

View File

@ -8,6 +8,7 @@
#include <openrct2/interface/themes.h>
#include <openrct2/interface/Window.h>
#include <openrct2/localisation/Language.h>
#include <openrct2/localisation/LocalisationService.h>
#include <openrct2/Version.h>
#include "InGameConsole.h"
@ -256,7 +257,7 @@ void InGameConsole::Draw(rct_drawpixelinfo * dpi) const
}
// TTF looks far better without the outlines
if (!gUseTrueTypeFont)
if (!LocalisationService_UseTrueTypeFont())
{
textColour |= COLOUR_FLAG_OUTLINE;
}

View File

@ -21,6 +21,7 @@
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/LocalisationService.h>
#include <openrct2/sprites.h>
#define WW 400
@ -249,7 +250,7 @@ static void window_about_openrct2_paint(rct_window *w, rct_drawpixelinfo *dpi)
// Copyright disclaimer; hidden when using truetype fonts to prevent
// the text from overlapping the changelog button.
if (!gUseTrueTypeFont)
if (!LocalisationService_UseTrueTypeFont())
{
gfx_draw_string_centred_wrapped(dpi, nullptr, x, y, width, STR_ABOUT_OPENRCT2_DESCRIPTION_3, w->colours[2]);
}

View File

@ -40,6 +40,7 @@
#include <openrct2/localisation/Date.h>
#include <openrct2/localisation/Language.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/LocalisationService.h>
#include <openrct2/platform/platform.h>
#include <openrct2/sprites.h>
#include <openrct2/util/Util.h>
@ -1150,7 +1151,7 @@ static void window_options_mousedown(rct_window *w, rct_widgetindex widgetIndex,
gDropdownItemsArgs[i - 1] = (uintptr_t)LanguagesDescriptors[i].native_name;
}
window_options_show_dropdown(w, widget, LANGUAGE_COUNT - 1);
dropdown_set_checked(gCurrentLanguage - 1, true);
dropdown_set_checked(LocalisationService_GetCurrentLanguage() - 1, true);
break;
case WIDX_DATE_FORMAT_DROPDOWN:
for (size_t i = 0; i < 4; i++) {
@ -1389,8 +1390,8 @@ static void window_options_dropdown(rct_window *w, rct_widgetindex widgetIndex,
break;
case WIDX_LANGUAGE_DROPDOWN:
{
sint32 fallbackLanguage = gCurrentLanguage;
if (dropdownIndex != gCurrentLanguage - 1) {
auto fallbackLanguage = LocalisationService_GetCurrentLanguage();
if (dropdownIndex != LocalisationService_GetCurrentLanguage() - 1) {
if (!language_open(dropdownIndex + 1))
{
// Failed to open language file, try to recover by falling
@ -1635,7 +1636,7 @@ static void window_options_invalidate(rct_window *w)
case WINDOW_OPTIONS_PAGE_CULTURE:
// Language
set_format_arg(0, char*, LanguagesDescriptors[gCurrentLanguage].native_name);
set_format_arg(0, char*, LanguagesDescriptors[LocalisationService_GetCurrentLanguage()].native_name);
// Currency: pounds, dollars, etc. (10 total)
window_options_culture_widgets[WIDX_CURRENCY].text = CurrencyDescriptors[gConfigGeneral.currency_format].stringId;

View File

@ -20,6 +20,7 @@
#include <openrct2/interface/themes.h>
#include <openrct2/localisation/Date.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/LocalisationService.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/sprites.h>
@ -282,7 +283,7 @@ static void window_scenarioselect_mousedown(rct_window *w, rct_widgetindex widge
static sint32 get_scenario_list_item_size()
{
if (!gUseTrueTypeFont)
if (!LocalisationService_UseTrueTypeFont())
return 24;
// Scenario title

View File

@ -64,7 +64,7 @@
#include "interface/Viewport.h"
#include "Intro.h"
#include "localisation/Date.h"
#include "localisation/Language.h"
#include "localisation/LocalisationService.h"
#include "network/DiscordService.h"
#include "network/http.h"
#include "network/network.h"
@ -74,6 +74,7 @@
using namespace OpenRCT2;
using namespace OpenRCT2::Audio;
using namespace OpenRCT2::Localisation;
using namespace OpenRCT2::Ui;
namespace OpenRCT2
@ -82,17 +83,18 @@ namespace OpenRCT2
{
private:
// Dependencies
IPlatformEnvironment * const _env = nullptr;
IAudioContext * const _audioContext = nullptr;
IUiContext * const _uiContext = nullptr;
std::shared_ptr<IPlatformEnvironment> const _env;
std::shared_ptr<IAudioContext> const _audioContext;
std::shared_ptr<IUiContext> const _uiContext;
// Services
std::shared_ptr<LocalisationService> _localisationService;
IObjectRepository * _objectRepository = nullptr;
IObjectManager * _objectManager = nullptr;
ITrackDesignRepository * _trackDesignRepository = nullptr;
IScenarioRepository * _scenarioRepository = nullptr;
#ifdef __ENABLE_DISCORD__
DiscordService * _discordService = nullptr;
std::unique_ptr<DiscordService> _discordService;
#endif
StdInOutConsole _stdInOutConsole;
@ -116,10 +118,14 @@ namespace OpenRCT2
static Context * Instance;
public:
Context(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
Context(
const std::shared_ptr<IPlatformEnvironment>& env,
const std::shared_ptr<IAudioContext>& audioContext,
const std::shared_ptr<IUiContext>& uiContext)
: _env(env),
_audioContext(audioContext),
_uiContext(uiContext)
_uiContext(uiContext),
_localisationService(std::make_shared<LocalisationService>(env))
{
Instance = this;
}
@ -128,7 +134,6 @@ namespace OpenRCT2
{
window_close_all();
http_dispose();
language_close_all();
object_manager_unload_all_objects();
gfx_object_check_all_images_freed();
gfx_unload_g2();
@ -140,9 +145,6 @@ namespace OpenRCT2
delete _titleScreen;
#ifdef __ENABLE_DISCORD__
delete _discordService;
#endif
delete _scenarioRepository;
delete _trackDesignRepository;
delete _objectManager;
@ -151,21 +153,26 @@ namespace OpenRCT2
Instance = nullptr;
}
IAudioContext * GetAudioContext() override
std::shared_ptr<IAudioContext> GetAudioContext() override
{
return _audioContext;
}
IUiContext * GetUiContext() override
std::shared_ptr<IUiContext> GetUiContext() override
{
return _uiContext;
}
IPlatformEnvironment * GetPlatformEnvironment() override
std::shared_ptr<IPlatformEnvironment> GetPlatformEnvironment() override
{
return _env;
}
Localisation::LocalisationService& GetLocalisationService() override
{
return *_localisationService;
}
IObjectManager * GetObjectManager() override
{
return _objectManager;
@ -344,22 +351,30 @@ namespace OpenRCT2
_trackDesignRepository = CreateTrackDesignRepository(_env);
_scenarioRepository = CreateScenarioRepository(_env);
#ifdef __ENABLE_DISCORD__
_discordService = new DiscordService();
_discordService = std::make_unique<DiscordService>();
#endif
if (!language_open(gConfigGeneral.language))
try
{
log_error("Failed to open configured language...");
if (!language_open(LANGUAGE_ENGLISH_UK))
_localisationService->OpenLanguage(gConfigGeneral.language, *_objectManager);
}
catch (const std::exception& e)
{
log_error("Failed to open configured language: %s", e.what());
try
{
log_fatal("Failed to open fallback language...");
_localisationService->OpenLanguage(LANGUAGE_ENGLISH_UK, *_objectManager);
}
catch (const std::exception&)
{
log_fatal("Failed to open fallback language: %s", e.what());
return false;
}
}
if (platform_process_is_elevated())
{
std::string elevationWarning = language_get_string(STR_ADMIN_NOT_RECOMMENDED);
std::string elevationWarning = _localisationService->GetString(STR_ADMIN_NOT_RECOMMENDED);
if (gOpenRCT2Headless)
{
Console::Error::WriteLine(elevationWarning.c_str());
@ -378,14 +393,14 @@ namespace OpenRCT2
// 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();
_objectRepository->LoadOrConstruct(_localisationService->GetCurrentLanguage());
// 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();
_trackDesignRepository->Scan(_localisationService->GetCurrentLanguage());
_scenarioRepository->Scan();
_scenarioRepository->Scan(_localisationService->GetCurrentLanguage());
TitleSequenceManager::Scan();
if (!gOpenRCT2Headless)
@ -548,7 +563,7 @@ namespace OpenRCT2
bool LoadBaseGraphics()
{
if (!gfx_load_g1(_env))
if (!gfx_load_g1(*_env))
{
return false;
}
@ -900,37 +915,19 @@ namespace OpenRCT2
}
};
class PlainContext final : public Context
{
std::unique_ptr<IPlatformEnvironment> _env;
std::unique_ptr<IAudioContext> _audioContext;
std::unique_ptr<IUiContext> _uiContext;
public:
PlainContext()
: PlainContext(CreatePlatformEnvironment(), CreateDummyAudioContext(), CreateDummyUiContext())
{
}
PlainContext(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
: Context(env, audioContext, uiContext)
{
_env = std::unique_ptr<IPlatformEnvironment>(env);
_audioContext = std::unique_ptr<IAudioContext>(audioContext);
_uiContext = std::unique_ptr<IUiContext>(uiContext);
}
};
Context * Context::Instance = nullptr;
IContext * CreateContext()
std::unique_ptr<IContext> CreateContext()
{
return new PlainContext();
return std::make_unique<Context>(CreatePlatformEnvironment(), CreateDummyAudioContext(), CreateDummyUiContext());
}
IContext * CreateContext(IPlatformEnvironment * env, Audio::IAudioContext * audioContext, IUiContext * uiContext)
std::unique_ptr<IContext> CreateContext(
const std::shared_ptr<IPlatformEnvironment>& env,
const std::shared_ptr<Audio::IAudioContext>& audioContext,
const std::shared_ptr<IUiContext>& uiContext)
{
return new Context(env, audioContext, uiContext);
return std::make_unique<Context>(env, audioContext, uiContext);
}
IContext * GetContext()

View File

@ -18,6 +18,7 @@
#include "common.h"
#include <memory>
#include <string>
interface IObjectManager;
@ -76,6 +77,11 @@ namespace OpenRCT2
interface IAudioContext;
}
namespace Localisation
{
class LocalisationService;
}
namespace Ui
{
interface IUiContext;
@ -88,9 +94,10 @@ namespace OpenRCT2
{
virtual ~IContext() = default;
virtual Audio::IAudioContext * GetAudioContext() abstract;
virtual Ui::IUiContext * GetUiContext() abstract;
virtual IPlatformEnvironment * GetPlatformEnvironment() abstract;
virtual std::shared_ptr<Audio::IAudioContext> GetAudioContext() abstract;
virtual std::shared_ptr<Ui::IUiContext> GetUiContext() abstract;
virtual std::shared_ptr<IPlatformEnvironment> GetPlatformEnvironment() abstract;
virtual Localisation::LocalisationService& GetLocalisationService() abstract;
virtual IObjectManager * GetObjectManager() abstract;
virtual IObjectRepository * GetObjectRepository() abstract;
virtual ITrackDesignRepository * GetTrackDesignRepository() abstract;
@ -111,8 +118,11 @@ namespace OpenRCT2
virtual std::string GetPathLegacy(sint32 pathId) abstract;
};
IContext * CreateContext();
IContext * CreateContext(IPlatformEnvironment * env, Audio::IAudioContext * audioContext, Ui::IUiContext * uiContext);
std::unique_ptr<IContext> CreateContext();
std::unique_ptr<IContext> CreateContext(
const std::shared_ptr<IPlatformEnvironment>& env,
const std::shared_ptr<Audio::IAudioContext>& audioContext,
const std::shared_ptr<Ui::IUiContext>& uiContext);
IContext * GetContext();
} // namespace OpenRCT2

View File

@ -109,9 +109,9 @@ private:
}
};
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment(DIRBASE_VALUES basePaths)
std::unique_ptr<IPlatformEnvironment> OpenRCT2::CreatePlatformEnvironment(DIRBASE_VALUES basePaths)
{
return new PlatformEnvironment(basePaths);
return std::make_unique<PlatformEnvironment>(basePaths);
}
static std::string GetOpenRCT2DirectoryName()
@ -123,7 +123,7 @@ static std::string GetOpenRCT2DirectoryName()
#endif
}
IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
std::unique_ptr<IPlatformEnvironment> OpenRCT2::CreatePlatformEnvironment()
{
auto subDirectory = GetOpenRCT2DirectoryName();

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <string>
#include "common.h"
@ -82,6 +83,7 @@ namespace OpenRCT2
virtual void SetBasePath(DIRBASE base, const std::string &path) abstract;
};
IPlatformEnvironment * CreatePlatformEnvironment(DIRBASE_VALUES basePaths);
IPlatformEnvironment * CreatePlatformEnvironment();
std::unique_ptr<IPlatformEnvironment> CreatePlatformEnvironment(DIRBASE_VALUES basePaths);
std::unique_ptr<IPlatformEnvironment> CreatePlatformEnvironment();
} // namespace OpenRCT2

View File

@ -157,7 +157,7 @@ void audio_populate_devices()
{
SafeFree(gAudioDevices);
IAudioContext * audioContext = OpenRCT2::GetContext()->GetAudioContext();
auto audioContext = OpenRCT2::GetContext()->GetAudioContext();
std::vector<std::string> devices = audioContext->GetOutputDevices();
// Replace blanks with localised unknown string

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "../common.h"
@ -59,5 +60,6 @@ namespace OpenRCT2::Audio
virtual void StopVehicleSounds() abstract;
};
IAudioContext * CreateDummyAudioContext();
std::unique_ptr<IAudioContext> CreateDummyAudioContext();
} // namespace OpenRCT2::Audio

View File

@ -28,13 +28,13 @@ using namespace OpenRCT2::Audio;
static IAudioMixer * GetMixer()
{
IAudioContext * audioContext = GetContext()->GetAudioContext();
auto audioContext = GetContext()->GetAudioContext();
return audioContext->GetMixer();
}
void Mixer_Init(const char * device)
{
IAudioContext * audioContext = GetContext()->GetAudioContext();
auto audioContext = GetContext()->GetAudioContext();
if (device == nullptr)
{
device = "";
@ -140,7 +140,7 @@ void * Mixer_Play_Music(sint32 pathId, sint32 loop, sint32 streaming)
{
const utf8 * path = context_get_path_legacy(pathId);
IAudioContext * audioContext = GetContext()->GetAudioContext();
auto audioContext = GetContext()->GetAudioContext();
IAudioSource * source = audioContext->CreateStreamFromWAV(path);
if (source != nullptr)
{

View File

@ -45,8 +45,8 @@ namespace OpenRCT2::Audio
void StopVehicleSounds() override { }
};
IAudioContext * CreateDummyAudioContext()
std::unique_ptr<IAudioContext> CreateDummyAudioContext()
{
return new DummyAudioContext();
return std::make_unique<DummyAudioContext>();
}
} // namespace OpenRCT2::Audio

View File

@ -399,12 +399,8 @@ static exitcode_t HandleCommandScanObjects([[maybe_unused]] CommandLineArgEnumer
auto context = std::unique_ptr<OpenRCT2::IContext>(OpenRCT2::CreateContext());
auto env = context->GetPlatformEnvironment();
auto objectRepository = std::unique_ptr<IObjectRepository>(CreateObjectRepository(env));
// HACK: set gCurrentLanguage otherwise it be wrong for the index file
gCurrentLanguage = gConfigGeneral.language;
objectRepository->Construct();
auto objectRepository = CreateObjectRepository(env);
objectRepository->Construct(gConfigGeneral.language);
return EXITCODE_OK;
}

View File

@ -742,7 +742,7 @@ bool config_find_or_browse_install_directory()
{
while (true)
{
IUiContext * uiContext = GetContext()->GetUiContext();
auto uiContext = GetContext()->GetUiContext();
uiContext->ShowMessageBox("OpenRCT2 needs files from the original RollerCoaster Tycoon 2 in order to work. \nPlease select the directory where you installed RollerCoaster Tycoon 2.");
std::string installPath = uiContext->ShowDirectoryDialog("Please select your RCT2 directory");

View File

@ -107,11 +107,11 @@ public:
* Queries and directories and loads the index header. If the index is up to date,
* the items are loaded from the index and returned, otherwise the index is rebuilt.
*/
std::vector<TItem> LoadOrBuild() const
std::vector<TItem> LoadOrBuild(sint32 language) const
{
std::vector<TItem> items;
auto scanResult = Scan();
auto readIndexResult = ReadIndexFile(scanResult.Stats);
auto readIndexResult = ReadIndexFile(language, scanResult.Stats);
if (std::get<0>(readIndexResult))
{
// Index was loaded
@ -120,15 +120,15 @@ public:
else
{
// Index was not loaded
items = Build(scanResult);
items = Build(language, scanResult);
}
return items;
}
std::vector<TItem> Rebuild() const
std::vector<TItem> Rebuild(sint32 language) const
{
auto scanResult = Scan();
auto items = Build(scanResult);
auto items = Build(language, scanResult);
return items;
}
@ -137,7 +137,7 @@ protected:
* Loads the given file and creates the item representing the data to store in the index.
* TODO Use std::optional when C++17 is available.
*/
virtual std::tuple<bool, TItem> Create(const std::string &path) const abstract;
virtual std::tuple<bool, TItem> Create(sint32 language, const std::string &path) const abstract;
/**
* Serialises an index item to the given stream.
@ -180,7 +180,8 @@ private:
return ScanResult(stats, files);
}
void BuildRange(const ScanResult &scanResult,
void BuildRange(sint32 language,
const ScanResult &scanResult,
size_t rangeStart,
size_t rangeEnd,
std::vector<TItem>& items,
@ -198,7 +199,7 @@ private:
log_verbose("FileIndex:Indexing '%s'", filePath.c_str());
}
auto item = Create(filePath);
auto item = Create(language, filePath);
if (std::get<0>(item))
{
items.push_back(std::get<1>(item));
@ -208,7 +209,7 @@ private:
}
}
std::vector<TItem> Build(const ScanResult &scanResult) const
std::vector<TItem> Build(sint32 language, const ScanResult &scanResult) const
{
std::vector<TItem> allItems;
Console::WriteLine("Building %s (%zu items)", _name.c_str(), scanResult.Files.size());
@ -245,6 +246,7 @@ private:
jobPool.AddTask(std::bind(&FileIndex<TItem>::BuildRange,
this,
language,
std::cref(scanResult),
rangeStart,
rangeStart + stepSize,
@ -262,7 +264,7 @@ private:
allItems.insert(allItems.end(), itr.begin(), itr.end());
}
WriteIndexFile(scanResult.Stats, allItems);
WriteIndexFile(language, scanResult.Stats, allItems);
}
auto endTime = std::chrono::high_resolution_clock::now();
@ -272,7 +274,7 @@ private:
return allItems;
}
std::tuple<bool, std::vector<TItem>> ReadIndexFile(const DirectoryStats &stats) const
std::tuple<bool, std::vector<TItem>> ReadIndexFile(sint32 language, const DirectoryStats &stats) const
{
bool loadedItems = false;
std::vector<TItem> items;
@ -289,7 +291,7 @@ private:
header.MagicNumber == _magicNumber &&
header.VersionA == FILE_INDEX_VERSION &&
header.VersionB == _version &&
header.LanguageId == gCurrentLanguage &&
header.LanguageId == language &&
header.Stats.TotalFiles == stats.TotalFiles &&
header.Stats.TotalFileSize == stats.TotalFileSize &&
header.Stats.FileDateModifiedChecksum == stats.FileDateModifiedChecksum &&
@ -318,7 +320,7 @@ private:
return std::make_tuple(loadedItems, items);
}
void WriteIndexFile(const DirectoryStats &stats, const std::vector<TItem> &items) const
void WriteIndexFile(sint32 language, const DirectoryStats &stats, const std::vector<TItem> &items) const
{
try
{
@ -331,7 +333,7 @@ private:
header.MagicNumber = _magicNumber;
header.VersionA = FILE_INDEX_VERSION;
header.VersionB = _version;
header.LanguageId = gCurrentLanguage;
header.LanguageId = language;
header.Stats = stats;
header.NumItems = (uint32)items.size();
fs.WriteValue(header);

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <stdarg.h>
#include <stdbool.h>
@ -52,6 +53,15 @@ namespace Guard
va_end(args);
}
template<typename T>
static void ArgumentNotNull(const std::shared_ptr<T>& argument, const char * message = nullptr, ...)
{
va_list args;
va_start(args, message);
Assert_VA(argument != nullptr, message, args);
va_end(args);
}
template<typename T>
static void ArgumentInRange(T argument, T min, T max, const char * message = nullptr, ...)
{

View File

@ -20,6 +20,11 @@
#include "../common.h"
#include "../interface/Colour.h"
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
struct rct_g1_element {
uint8* offset; // 0x00
sint16 width; // 0x04
@ -281,7 +286,7 @@ void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, sint16 left, sint16 top, sint16
void gfx_filter_rect(rct_drawpixelinfo *dpi, sint32 left, sint32 top, sint32 right, sint32 bottom, FILTER_PALETTE_ID palette);
// sprite
bool gfx_load_g1(void * platformEnvironment);
bool gfx_load_g1(const OpenRCT2::IPlatformEnvironment& env);
bool gfx_load_g2();
bool gfx_load_csg();
void gfx_unload_g1();

View File

@ -17,6 +17,7 @@
#include "../core/Util.hpp"
#include "../localisation/FormatCodes.h"
#include "../localisation/Language.h"
#include "../localisation/LocalisationService.h"
#include "../sprites.h"
#include "Drawing.h"
#include "Font.h"
@ -158,7 +159,7 @@ sint32 font_get_line_height(sint32 fontSpriteBase)
{
sint32 fontSize = font_get_size_from_sprite_base(fontSpriteBase);
#ifndef NO_TTF
if (gUseTrueTypeFont) {
if (LocalisationService_UseTrueTypeFont()) {
return gCurrentTTFFontSet->size[fontSize].line_height;
} else {
#endif // NO_TTF
@ -265,7 +266,7 @@ bool font_supports_string_ttf(const utf8 *text, sint32 fontSize)
bool font_supports_string(const utf8 *text, sint32 fontSize)
{
if (gUseTrueTypeFont) {
if (LocalisationService_UseTrueTypeFont()) {
return font_supports_string_ttf(text, fontSize);
} else {
return font_supports_string_sprite(text);

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include "../common.h"
enum DRAWING_ENGINE
@ -40,8 +41,14 @@ enum DRAWING_ENGINE_FLAGS
struct rct_drawpixelinfo;
struct rct_palette_entry;
namespace OpenRCT2::Ui
{
interface IUiContext;
} // namespace OpenRCT2::Ui
namespace OpenRCT2::Drawing
{
enum class DRAWING_ENGINE_TYPE;
interface IDrawingContext;
interface IDrawingEngine
@ -70,6 +77,12 @@ namespace OpenRCT2::Drawing
virtual void InvalidateImage(uint32 image) abstract;
};
interface IDrawingEngineFactory
{
virtual ~IDrawingEngineFactory() { }
virtual std::unique_ptr<IDrawingEngine> Create(DRAWING_ENGINE_TYPE type, const std::shared_ptr<OpenRCT2::Ui::IUiContext>& uiContext) abstract;
};
interface IRainDrawer
{
virtual ~IRainDrawer() { }

View File

@ -31,8 +31,8 @@ using namespace OpenRCT2::Drawing;
using namespace OpenRCT2::Paint;
using namespace OpenRCT2::Ui;
static sint32 _drawingEngineType = DRAWING_ENGINE_SOFTWARE;
static IDrawingEngine * _drawingEngine = nullptr;
static sint32 _drawingEngineType = DRAWING_ENGINE_SOFTWARE;
static std::shared_ptr<IDrawingEngine> _drawingEngine;
// TODO move this to Context
static Painter * _painter = nullptr;
@ -71,7 +71,8 @@ void drawing_engine_init()
auto context = GetContext();
auto uiContext = context->GetUiContext();
auto drawingEngine = uiContext->CreateDrawingEngine((DRAWING_ENGINE_TYPE)_drawingEngineType);
auto drawingEngineFactory = uiContext->GetDrawingEngineFactory();
auto drawingEngine = drawingEngineFactory->Create((DRAWING_ENGINE_TYPE)_drawingEngineType, uiContext);
if (drawingEngine == nullptr)
{
@ -98,14 +99,12 @@ void drawing_engine_init()
{
drawingEngine->Initialise();
drawingEngine->SetVSync(gConfigGeneral.use_vsync);
_drawingEngine = drawingEngine;
_drawingEngine = std::shared_ptr<IDrawingEngine>(std::move(drawingEngine));
}
catch (const std::exception &ex)
{
delete _painter;
_painter = nullptr;
delete drawingEngine;
drawingEngine = nullptr;
if (_drawingEngineType == DRAWING_ENGINE_SOFTWARE)
{
_drawingEngineType = DRAWING_ENGINE_NONE;
@ -131,7 +130,7 @@ void drawing_engine_resize()
{
if (_drawingEngine != nullptr)
{
IUiContext * uiContext = GetContext()->GetUiContext();
auto uiContext = GetContext()->GetUiContext();
_drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight());
}
}
@ -149,7 +148,7 @@ void drawing_engine_draw()
if (_drawingEngine != nullptr && _painter != nullptr)
{
_drawingEngine->BeginDraw();
_painter->Paint(_drawingEngine);
_painter->Paint(*_drawingEngine);
_drawingEngine->EndDraw();
}
}
@ -164,7 +163,6 @@ void drawing_engine_copy_rect(sint32 x, sint32 y, sint32 width, sint32 height, s
void drawing_engine_dispose()
{
delete _drawingEngine;
delete _painter;
_drawingEngine = nullptr;
_painter = nullptr;

View File

@ -18,6 +18,7 @@
#include "../config/Config.h"
#include "../interface/Colour.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "../paint/Paint.h"
#include "../sprites.h"
#include "Drawing.h"
@ -1459,7 +1460,7 @@ sint32 scrolling_text_setup(paint_session * session, rct_string_id stringId, uin
const sint16* scrollingModePositions = _scrollPositions[scrollingMode];
memset(scrollText->bitmap, 0, 320 * 8);
if (gUseTrueTypeFont) {
if (LocalisationService_UseTrueTypeFont()) {
scrolling_text_set_bitmap_for_ttf(scrollString, scroll, scrollText->bitmap, scrollingModePositions);
} else {
scrolling_text_set_bitmap_for_sprite(scrollString, scroll, scrollText->bitmap, scrollingModePositions);

View File

@ -227,14 +227,12 @@ bool gTinyFontAntiAliased = false;
*
* rct2: 0x00678998
*/
bool gfx_load_g1(void * platformEnvironment)
bool gfx_load_g1(const IPlatformEnvironment& env)
{
auto env = (IPlatformEnvironment *)platformEnvironment;
log_verbose("gfx_load_g1(...)");
try
{
auto path = Path::Combine(env->GetDirectoryPath(DIRBASE::RCT2, DIRID::DATA), "g1.dat");
auto path = Path::Combine(env.GetDirectoryPath(DIRBASE::RCT2, DIRID::DATA), "g1.dat");
auto fs = FileStream(path, FILE_MODE_OPEN);
_g1.header = fs.ReadValue<rct_g1_header>();
@ -269,7 +267,7 @@ bool gfx_load_g1(void * platformEnvironment)
log_fatal("Unable to load g1 graphics");
if (!gOpenRCT2Headless)
{
IUiContext * uiContext = GetContext()->GetUiContext();
auto uiContext = GetContext()->GetUiContext();
uiContext->ShowMessageBox("Unable to load g1.dat. Your RollerCoaster Tycoon 2 path may be incorrectly set.");
}
return false;
@ -332,7 +330,7 @@ bool gfx_load_g2()
log_fatal("Unable to load g2 graphics");
if (!gOpenRCT2Headless)
{
IUiContext * uiContext = GetContext()->GetUiContext();
auto uiContext = GetContext()->GetUiContext();
uiContext->ShowMessageBox("Unable to load g2.dat");
}
}

View File

@ -20,6 +20,7 @@
#include "../drawing/Drawing.h"
#include "../interface/Viewport.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "../platform/platform.h"
#include "../sprites.h"
#include "../util/Util.h"
@ -822,7 +823,7 @@ void ttf_draw_string(rct_drawpixelinfo *dpi, const_utf8string text, sint32 colou
info.x = x;
info.y = y;
if (gUseTrueTypeFont) {
if (LocalisationService_UseTrueTypeFont()) {
info.flags |= TEXT_DRAW_FLAG_TTF;
}
@ -851,7 +852,7 @@ static sint32 ttf_get_string_width(const utf8 *text)
info.maxY = 0;
info.flags |= TEXT_DRAW_FLAG_NO_DRAW;
if (gUseTrueTypeFont) {
if (LocalisationService_UseTrueTypeFont()) {
info.flags |= TEXT_DRAW_FLAG_TTF;
}
@ -877,7 +878,7 @@ void gfx_draw_string_with_y_offsets(rct_drawpixelinfo *dpi, const utf8 *text, si
info.flags |= TEXT_DRAW_FLAG_Y_OFFSET_EFFECT;
if (!forceSpriteFont && gUseTrueTypeFont) {
if (!forceSpriteFont && LocalisationService_UseTrueTypeFont()) {
info.flags |= TEXT_DRAW_FLAG_TTF;
}

View File

@ -21,6 +21,7 @@
#include "../config/Config.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "../OpenRCT2.h"
#include "../platform/platform.h"
#include "TTF.h"
@ -157,7 +158,7 @@ static void ttf_surface_cache_dispose_all()
void ttf_toggle_hinting()
{
if (!gUseTrueTypeFont)
if (!LocalisationService_UseTrueTypeFont())
{
return;
}

View File

@ -133,7 +133,7 @@ void X8RainDrawer::Restore()
#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
#endif
X8DrawingEngine::X8DrawingEngine(Ui::IUiContext * uiContext)
X8DrawingEngine::X8DrawingEngine(const std::shared_ptr<Ui::IUiContext>& uiContext)
{
_drawingContext = new X8DrawingContext(this);
#ifdef __ENABLE_LIGHTFX__

View File

@ -91,7 +91,7 @@ namespace OpenRCT2
X8DrawingContext * _drawingContext;
public:
explicit X8DrawingEngine(Ui::IUiContext * uiContext);
explicit X8DrawingEngine(const std::shared_ptr<Ui::IUiContext>& uiContext);
~X8DrawingEngine() override;
void Initialise() override;

View File

@ -21,6 +21,9 @@
#include "../drawing/TTF.h"
#include "../localisation/Language.h"
#include "../localisation/LocalisationService.h"
using namespace OpenRCT2::Localisation;
#ifndef NO_TTF
uint8 const HINTING_DISABLED = 0;
@ -100,19 +103,19 @@ TTFFontSetDescriptor TTFFontArialUnicode = { {
// clang-format on
#endif // NO_TTF
static void LoadSpriteFont()
static void LoadSpriteFont(LocalisationService& localisationService)
{
ttf_dispose();
gUseTrueTypeFont = false;
localisationService.UseTrueTypeFont(false);
#ifndef NO_TTF
gCurrentTTFFontSet = nullptr;
#endif // NO_TTF
}
#ifndef NO_TTF
static bool LoadFont(TTFFontSetDescriptor * font)
static bool LoadFont(LocalisationService& localisationService, TTFFontSetDescriptor * font)
{
gUseTrueTypeFont = true;
localisationService.UseTrueTypeFont(true);
gCurrentTTFFontSet = font;
ttf_dispose();
@ -120,7 +123,7 @@ static bool LoadFont(TTFFontSetDescriptor * font)
return fontInitialised;
}
static bool LoadCustomConfigFont()
static bool LoadCustomConfigFont(LocalisationService& localisationService)
{
static TTFFontSetDescriptor TTFFontCustom = { {
{ gConfigFonts.file_name, gConfigFonts.font_name, gConfigFonts.size_tiny, gConfigFonts.x_offset, gConfigFonts.y_offset,
@ -134,7 +137,7 @@ static bool LoadCustomConfigFont()
} };
ttf_dispose();
gUseTrueTypeFont = true;
localisationService.UseTrueTypeFont(true);
gCurrentTTFFontSet = &TTFFontCustom;
bool fontInitialised = ttf_initialise();
@ -142,16 +145,17 @@ static bool LoadCustomConfigFont()
}
#endif // NO_TTF
void TryLoadFonts()
void TryLoadFonts(LocalisationService& localisationService)
{
#ifndef NO_TTF
TTFontFamily const * fontFamily = LanguagesDescriptors[gCurrentLanguage].font_family;
auto currentLanguage = localisationService.GetCurrentLanguage();
TTFontFamily const * fontFamily = LanguagesDescriptors[currentLanguage].font_family;
if (fontFamily != FAMILY_OPENRCT2_SPRITE)
{
if (!String::IsNullOrEmpty(gConfigFonts.file_name))
{
if (LoadCustomConfigFont())
if (LoadCustomConfigFont(localisationService))
{
return;
}
@ -160,7 +164,7 @@ void TryLoadFonts()
for (auto &font : *fontFamily)
{
if (LoadFont(font))
if (LoadFont(localisationService, font))
{
return;
}
@ -175,7 +179,7 @@ void TryLoadFonts()
for (auto &font : TTFFamilySansSerif)
{
if (LoadFont(font))
if (LoadFont(localisationService, font))
{
return;
}
@ -188,5 +192,5 @@ void TryLoadFonts()
}
}
#endif // NO_TTF
LoadSpriteFont();
LoadSpriteFont(localisationService);
}

View File

@ -17,6 +17,11 @@
#ifndef OPENRCT2_FONTS_H
#define OPENRCT2_FONTS_H
namespace OpenRCT2::Localisation
{
class LocalisationService;
}
#include "../drawing/Font.h"
#ifndef NO_TTF
@ -35,6 +40,6 @@ extern TTFFontSetDescriptor TTFFontArialUnicode;
#define FONT(x) FONT_OPENRCT2_SPRITE
#endif // NO_TTF
void TryLoadFonts();
void TryLoadFonts(OpenRCT2::Localisation::LocalisationService& localisationService);
#endif // OPENRCT2_FONTS_H

View File

@ -448,7 +448,6 @@ sint32 cmdline_for_screenshot(const char * * argv, sint32 argc, ScreenshotOption
{
std::printf("%s\n", e.what());
drawing_engine_dispose();
delete context;
return -1;
}
@ -518,7 +517,6 @@ sint32 cmdline_for_screenshot(const char * * argv, sint32 argc, ScreenshotOption
{
std::printf("Weather can only be set to an integer value from 1 till 6.");
drawing_engine_dispose();
delete context;
return -1;
}
@ -583,6 +581,5 @@ sint32 cmdline_for_screenshot(const char * * argv, sint32 argc, ScreenshotOption
free(dpi.bits);
drawing_engine_dispose();
}
delete context;
return 1;
}

View File

@ -22,10 +22,10 @@
#include "../interface/Fonts.h"
#include "../interface/FontFamilies.h"
#include "../object/ObjectManager.h"
#include "LanguagePack.h"
#include "../platform/platform.h"
#include "LanguagePack.h"
#include "Localisation.h"
#include "LocalisationService.h"
// clang-format off
const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] =
@ -55,12 +55,6 @@ const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] =
};
// clang-format on
sint32 gCurrentLanguage = LANGUAGE_UNDEFINED;
bool gUseTrueTypeFont = false;
static ILanguagePack * _languageFallback = nullptr;
static ILanguagePack * _languageCurrent = nullptr;
// clang-format off
const utf8 BlackUpArrowString[] = { (utf8)(uint8)0xC2, (utf8)(uint8)0x8E, (utf8)(uint8)0xE2, (utf8)(uint8)0x96, (utf8)(uint8)0xB2, (utf8)(uint8)0x00 };
const utf8 BlackDownArrowString[] = { (utf8)(uint8)0xC2, (utf8)(uint8)0x8E, (utf8)(uint8)0xE2, (utf8)(uint8)0x96, (utf8)(uint8)0xBC, (utf8)(uint8)0x00 };
@ -100,130 +94,53 @@ uint8 language_get_id_from_locale(const char * locale)
const char * language_get_string(rct_string_id id)
{
const char * result = nullptr;
if (id == STR_EMPTY)
{
result = "";
}
else if (id != STR_NONE)
{
if (_languageCurrent != nullptr)
{
result = _languageCurrent->GetString(id);
}
if (result == nullptr && _languageFallback != nullptr)
{
result = _languageFallback->GetString(id);
}
if (result == nullptr)
{
result = "(undefined string)";
}
}
return result;
}
static utf8 * GetLanguagePath(utf8 * buffer, size_t bufferSize, uint32 languageId)
{
const char * locale = LanguagesDescriptors[languageId].locale;
platform_get_openrct_data_path(buffer, bufferSize);
Path::Append(buffer, bufferSize, "language");
Path::Append(buffer, bufferSize, locale);
String::Append(buffer, bufferSize, ".txt");
return buffer;
const auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
return localisationService.GetString(id);
}
bool language_open(sint32 id)
{
char filename[MAX_PATH];
language_close_all();
if (id == LANGUAGE_UNDEFINED)
auto context = OpenRCT2::GetContext();
auto& localisationService = context->GetLocalisationService();
auto objectManager = context->GetObjectManager();
try
{
localisationService.OpenLanguage(id, *objectManager);
return true;
}
catch (const std::exception&)
{
return false;
}
if (id != LANGUAGE_ENGLISH_UK)
{
GetLanguagePath(filename, sizeof(filename), LANGUAGE_ENGLISH_UK);
_languageFallback = LanguagePackFactory::FromFile(LANGUAGE_ENGLISH_UK, filename);
}
GetLanguagePath(filename, sizeof(filename), id);
_languageCurrent = LanguagePackFactory::FromFile(id, filename);
if (_languageCurrent != nullptr)
{
gCurrentLanguage = id;
TryLoadFonts();
// Objects and their localised strings need to be refreshed
auto context = OpenRCT2::GetContext();
context->GetObjectManager()->ResetObjects();
return true;
}
return false;
}
void language_close_all()
{
SafeDelete(_languageFallback);
SafeDelete(_languageCurrent);
gCurrentLanguage = LANGUAGE_UNDEFINED;
}
constexpr rct_string_id NONSTEX_BASE_STRING_ID = 3463;
constexpr uint16 MAX_OBJECT_CACHED_STRINGS = 2048;
bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_string_id *outStringIds)
{
outStringIds[0] = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename, 0);
outStringIds[1] = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename, 1);
outStringIds[2] = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename, 2);
const auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
auto result = localisationService.GetLocalisedScenarioStrings(scenarioFilename);
outStringIds[0] = std::get<0>(result);
outStringIds[1] = std::get<1>(result);
outStringIds[2] = std::get<2>(result);
return
outStringIds[0] != STR_NONE ||
outStringIds[1] != STR_NONE ||
outStringIds[2] != STR_NONE;
}
static bool _availableObjectStringIdsInitialised = false;
static std::stack<rct_string_id> _availableObjectStringIds;
void language_free_object_string(rct_string_id stringId)
{
if (stringId != 0)
{
if (_languageCurrent != nullptr)
{
_languageCurrent->RemoveString(stringId);
}
_availableObjectStringIds.push(stringId);
}
auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
localisationService.FreeObjectString(stringId);
}
rct_string_id language_get_object_override_string_id(const char * identifier, uint8 index)
{
if (_languageCurrent == nullptr)
{
return STR_NONE;
}
return _languageCurrent->GetObjectOverrideStringId(identifier, index);
const auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
return localisationService.GetObjectOverrideStringId(identifier, index);
}
rct_string_id language_allocate_object_string(const std::string &target)
{
if (!_availableObjectStringIdsInitialised)
{
_availableObjectStringIdsInitialised = true;
for (rct_string_id stringId = NONSTEX_BASE_STRING_ID + MAX_OBJECT_CACHED_STRINGS; stringId >= NONSTEX_BASE_STRING_ID; stringId--)
{
_availableObjectStringIds.push(stringId);
}
}
rct_string_id stringId = _availableObjectStringIds.top();
_availableObjectStringIds.pop();
_languageCurrent->SetString(stringId, target);
return stringId;
auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
return localisationService.AllocateObjectString(target);
}

View File

@ -86,9 +86,6 @@ struct language_descriptor {
extern const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT];
extern sint32 gCurrentLanguage;
extern bool gUseTrueTypeFont;
extern const utf8 BlackUpArrowString[];
extern const utf8 BlackDownArrowString[];
extern const utf8 BlackLeftArrowString[];
@ -98,7 +95,6 @@ extern const utf8 CheckBoxMarkString[];
uint8 language_get_id_from_locale(const char * locale);
const char *language_get_string(rct_string_id id);
bool language_open(sint32 id);
void language_close_all();
uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr);
utf8 *utf8_write_codepoint(utf8 *dst, uint32 codepoint);

View File

@ -0,0 +1,166 @@
#pragma region Copyright (c) 2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include <stdexcept>
#include "../Context.h"
#include "../core/Path.hpp"
#include "../interface/Fonts.h"
#include "../object/ObjectManager.h"
#include "../PlatformEnvironment.h"
#include "Language.h"
#include "LanguagePack.h"
#include "LocalisationService.h"
#include "StringIds.h"
using namespace OpenRCT2;
using namespace OpenRCT2::Localisation;
static constexpr rct_string_id NONSTEX_BASE_STRING_ID = 3463;
static constexpr uint16 MAX_OBJECT_CACHED_STRINGS = 2048;
LocalisationService::LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env)
{
for (rct_string_id stringId = NONSTEX_BASE_STRING_ID + MAX_OBJECT_CACHED_STRINGS; stringId >= NONSTEX_BASE_STRING_ID; stringId--)
{
_availableObjectStringIds.push(stringId);
}
}
// Define implementation here to avoid including LanguagePack.h in header
LocalisationService::~LocalisationService()
{
}
const char * LocalisationService::GetString(rct_string_id id) const
{
const char * result = nullptr;
if (id == STR_EMPTY)
{
result = "";
}
else if (id != STR_NONE)
{
if (_languageCurrent != nullptr)
{
result = _languageCurrent->GetString(id);
}
if (result == nullptr && _languageFallback != nullptr)
{
result = _languageFallback->GetString(id);
}
if (result == nullptr)
{
result = "(undefined string)";
}
}
return result;
}
std::string LocalisationService::GetLanguagePath(uint32 languageId) const
{
auto locale = std::string(LanguagesDescriptors[languageId].locale);
auto languageDirectory = _env->GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::LANGUAGE);
auto languagePath = Path::Combine(languageDirectory, locale + ".txt");
return languagePath;
}
void LocalisationService::OpenLanguage(sint32 id, IObjectManager& objectManager)
{
CloseLanguages();
if (id == LANGUAGE_UNDEFINED)
{
throw std::invalid_argument("id was undefined");
}
std::string filename;
if (id != LANGUAGE_ENGLISH_UK)
{
filename = GetLanguagePath(LANGUAGE_ENGLISH_UK);
_languageFallback = std::unique_ptr<ILanguagePack>(LanguagePackFactory::FromFile(LANGUAGE_ENGLISH_UK, filename.c_str()));
}
filename = GetLanguagePath(id);
_languageCurrent = std::unique_ptr<ILanguagePack>(LanguagePackFactory::FromFile(id, filename.c_str()));
if (_languageCurrent != nullptr)
{
_currentLanguage = id;
TryLoadFonts(*this);
// Objects and their localised strings need to be refreshed
objectManager.ResetObjects();
}
else
{
throw std::runtime_error("Unable to open language " + std::to_string(id));
}
}
void LocalisationService::CloseLanguages()
{
_languageFallback = nullptr;
_languageCurrent = nullptr;
_currentLanguage = LANGUAGE_UNDEFINED;
}
std::tuple<rct_string_id, rct_string_id, rct_string_id> LocalisationService::GetLocalisedScenarioStrings(const std::string& scenarioFilename) const
{
auto result0 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 0);
auto result1 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 1);
auto result2 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 2);
return std::make_tuple(result0, result1, result2);
}
rct_string_id LocalisationService::GetObjectOverrideStringId(const char * identifier, uint8 index) const
{
if (_languageCurrent == nullptr)
{
return STR_NONE;
}
return _languageCurrent->GetObjectOverrideStringId(identifier, index);
}
rct_string_id LocalisationService::AllocateObjectString(const std::string& target)
{
auto stringId = _availableObjectStringIds.top();
_availableObjectStringIds.pop();
_languageCurrent->SetString(stringId, target);
return stringId;
}
void LocalisationService::FreeObjectString(rct_string_id stringId)
{
if (stringId != STR_EMPTY)
{
if (_languageCurrent != nullptr)
{
_languageCurrent->RemoveString(stringId);
}
_availableObjectStringIds.push(stringId);
}
}
sint32 LocalisationService_GetCurrentLanguage()
{
const auto& localisationService = GetContext()->GetLocalisationService();
return localisationService.GetCurrentLanguage();
}
bool LocalisationService_UseTrueTypeFont()
{
const auto& localisationService = GetContext()->GetLocalisationService();
return localisationService.UseTrueTypeFont();
}

View File

@ -0,0 +1,66 @@
#pragma region Copyright (c) 2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include <memory>
#include <stack>
#include <string>
#include <tuple>
#include "../common.h"
interface ILanguagePack;
interface IObjectManager;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
namespace OpenRCT2::Localisation
{
class LocalisationService
{
private:
const std::shared_ptr<IPlatformEnvironment> _env;
sint32 _currentLanguage{};
bool _useTrueTypeFont{};
std::unique_ptr<ILanguagePack> _languageFallback;
std::unique_ptr<ILanguagePack> _languageCurrent;
std::stack<rct_string_id> _availableObjectStringIds;
public:
sint32 GetCurrentLanguage() const { return _currentLanguage; }
bool UseTrueTypeFont() const { return _useTrueTypeFont; }
void UseTrueTypeFont(bool value) { _useTrueTypeFont = value; }
LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env);
~LocalisationService();
const char * GetString(rct_string_id id) const;
std::tuple<rct_string_id, rct_string_id, rct_string_id> GetLocalisedScenarioStrings(const std::string& scenarioFilename) const;
rct_string_id GetObjectOverrideStringId(const char * identifier, uint8 index) const;
std::string GetLanguagePath(uint32 languageId) const;
void OpenLanguage(sint32 id, IObjectManager& objectManager);
void CloseLanguages();
rct_string_id AllocateObjectString(const std::string& target);
void FreeObjectString(rct_string_id stringId);
};
}
// Legacy getters
// TODO Remove usages of these and instead call via shared reference
sint32 LocalisationService_GetCurrentLanguage();
bool LocalisationService_UseTrueTypeFont();

View File

@ -30,7 +30,7 @@ constexpr const char * APPLICATION_ID = "378612438200877056";
constexpr const char * STEAM_APP_ID = nullptr;
constexpr const uint32 REFRESH_INTERVAL = 5 * GAME_UPDATE_FPS; // 5 seconds
static void OnReady()
static void OnReady(const DiscordUser * request)
{
log_verbose("DiscordService::OnReady()");
}

View File

@ -142,7 +142,7 @@ Network::~Network()
CloseConnection();
}
void Network::SetEnvironment(IPlatformEnvironment * env)
void Network::SetEnvironment(const std::shared_ptr<IPlatformEnvironment>& env)
{
_env = env;
}
@ -2545,9 +2545,9 @@ void Network::Client_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacke
network_chat_show_server_greeting();
}
void network_set_env(void * env)
void network_set_env(const std::shared_ptr<IPlatformEnvironment>& env)
{
gNetwork.SetEnvironment((IPlatformEnvironment *)env);
gNetwork.SetEnvironment(env);
}
void network_close()
@ -3327,7 +3327,7 @@ sint32 network_get_pickup_peep_old_x(uint8 playerid) { return _pickup_peep_old_x
void network_send_chat(const char* text) {}
void network_send_password(const char* password) {}
void network_close() {}
void network_set_env(void * env) {}
void network_set_env(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>&) {}
void network_shutdown_client() {}
void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <string>
enum {
@ -49,12 +50,16 @@ struct GameAction;
struct rct_peep;
struct LocationXYZ16;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
#ifndef DISABLE_NETWORK
#include <array>
#include <list>
#include <set>
#include <memory>
#include <vector>
#include <functional>
#include <fstream>
@ -79,17 +84,12 @@ enum {
struct ObjectRepositoryItem;
namespace OpenRCT2
{
interface IPlatformEnvironment;
}
class Network
{
public:
Network();
~Network();
void SetEnvironment(OpenRCT2::IPlatformEnvironment * env);
void SetEnvironment(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
bool Init();
void Close();
bool BeginClient(const char* host, uint16 port);
@ -259,7 +259,7 @@ private:
std::string _chatLogFilenameFormat = "%Y%m%d-%H%M%S.txt";
std::string _serverLogPath;
std::string _serverLogFilenameFormat = "%Y%m%d-%H%M%S.txt";
OpenRCT2::IPlatformEnvironment * _env = nullptr;
std::shared_ptr<OpenRCT2::IPlatformEnvironment> _env;
void UpdateServer();
void UpdateClient();
@ -301,7 +301,7 @@ private:
#endif /* DISABLE_NETWORK */
void network_set_env(void * env);
void network_set_env(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
void network_close();
void network_shutdown_client();
sint32 network_begin_client(const char *host, sint32 port);

View File

@ -76,6 +76,11 @@ std::string Object::GetString(uint8 index) const
return sz;
}
std::string Object::GetString(sint32 language, uint8 index) const
{
return GetStringTable().GetString(language, index);
}
rct_object_entry Object::GetScgWallsHeader()
{
return Object::CreateHeader("SCGWALLS", 207140231, 3518650219);
@ -711,6 +716,11 @@ std::string Object::GetName() const
return GetString(OBJ_STRING_ID_NAME);
}
std::string Object::GetName(sint32 language) const
{
return GetString(language, OBJ_STRING_ID_NAME);
}
#ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic pop
#endif

View File

@ -147,6 +147,7 @@ protected:
std::string GetOverrideString(uint8 index) const;
std::string GetString(uint8 index) const;
std::string GetString(sint32 language, uint8 index) const;
void SetSourceGame(const uint8 sourceGame);
bool IsRCT1Object();
@ -172,6 +173,7 @@ public:
virtual uint8 GetObjectType() const final { return _objectEntry.flags & 0x0F; }
virtual std::string GetName() const;
virtual std::string GetName(sint32 language) const;
virtual void SetRepositoryItem(ObjectRepositoryItem * item) const { }

View File

@ -43,6 +43,7 @@
#include "../config/Config.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "../object/Object.h"
#include "ObjectList.h"
#include "../platform/platform.h"
@ -86,21 +87,21 @@ private:
IObjectRepository& _objectRepository;
public:
explicit ObjectFileIndex(IObjectRepository& objectRepository, IPlatformEnvironment * env) :
explicit ObjectFileIndex(IObjectRepository& objectRepository, const IPlatformEnvironment& env) :
FileIndex("object index",
MAGIC_NUMBER,
VERSION,
env->GetFilePath(PATHID::CACHE_OBJECTS),
env.GetFilePath(PATHID::CACHE_OBJECTS),
std::string(PATTERN),
std::vector<std::string>({
env->GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })),
env.GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT),
env.GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })),
_objectRepository(objectRepository)
{
}
public:
std::tuple<bool, ObjectRepositoryItem> Create(const std::string &path) const override
std::tuple<bool, ObjectRepositoryItem> Create(sint32 language, const std::string &path) const override
{
auto extension = Path::GetExtension(path);
if (String::Equals(extension, ".json", true))
@ -111,7 +112,7 @@ public:
ObjectRepositoryItem item = { 0 };
item.ObjectEntry = *object->GetObjectEntry();
item.Path = String::Duplicate(path);
item.Name = String::Duplicate(object->GetName());
item.Name = String::Duplicate(object->GetName(language));
object->SetRepositoryItem(&item);
delete object;
return std::make_tuple(true, item);
@ -208,15 +209,15 @@ private:
class ObjectRepository final : public IObjectRepository
{
IPlatformEnvironment * const _env = nullptr;
ObjectFileIndex const _fileIndex;
std::vector<ObjectRepositoryItem> _items;
ObjectEntryMap _itemMap;
std::shared_ptr<IPlatformEnvironment> const _env;
ObjectFileIndex const _fileIndex;
std::vector<ObjectRepositoryItem> _items;
ObjectEntryMap _itemMap;
public:
explicit ObjectRepository(IPlatformEnvironment * env)
explicit ObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env),
_fileIndex(*this, env)
_fileIndex(*this, *env)
{
}
@ -225,17 +226,17 @@ public:
ClearItems();
}
void LoadOrConstruct() override
void LoadOrConstruct(sint32 language) override
{
ClearItems();
auto items = _fileIndex.LoadOrBuild();
auto items = _fileIndex.LoadOrBuild(language);
AddItems(items);
SortItems();
}
void Construct() override
void Construct(sint32 language) override
{
auto items = _fileIndex.Rebuild();
auto items = _fileIndex.Rebuild(language);
AddItems(items);
SortItems();
}
@ -445,7 +446,8 @@ private:
void ScanObject(const std::string &path)
{
auto result = _fileIndex.Create(path);
auto language = LocalisationService_GetCurrentLanguage();
auto result = _fileIndex.Create(language, path);
if (std::get<0>(result))
{
auto ori = std::get<1>(result);
@ -637,7 +639,7 @@ private:
}
};
IObjectRepository * CreateObjectRepository(IPlatformEnvironment * env)
IObjectRepository * CreateObjectRepository(const std::shared_ptr<IPlatformEnvironment>& env)
{
return new ObjectRepository(env);
}
@ -665,8 +667,9 @@ const rct_object_entry * object_list_find(rct_object_entry * entry)
void object_list_load()
{
auto context = GetContext();
IObjectRepository * objectRepository = context->GetObjectRepository();
objectRepository->LoadOrConstruct();
const auto& localisationService = context->GetLocalisationService();
auto objectRepository = context->GetObjectRepository();
objectRepository->LoadOrConstruct(localisationService.GetCurrentLanguage());
IObjectManager * objectManager = context->GetObjectManager();
objectManager->UnloadAll();

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <vector>
#include "../common.h"
#include "../object/Object.h"
@ -28,6 +29,11 @@ namespace OpenRCT2
interface IPlatformEnvironment;
}
namespace OpenRCT2::Localisation
{
class LocalisationService;
}
struct rct_drawpixelinfo;
struct ObjectRepositoryItem
@ -58,8 +64,8 @@ interface IObjectRepository
{
virtual ~IObjectRepository() = default;
virtual void LoadOrConstruct() abstract;
virtual void Construct() abstract;
virtual void LoadOrConstruct(sint32 language) abstract;
virtual void Construct(sint32 language) abstract;
virtual size_t GetNumObjects() const abstract;
virtual const ObjectRepositoryItem * GetObjects() const abstract;
virtual const ObjectRepositoryItem * FindObject(const utf8 * name) const abstract;
@ -77,7 +83,7 @@ interface IObjectRepository
virtual void WritePackedObjects(IStream * stream, std::vector<const ObjectRepositoryItem *> &objects) abstract;
};
IObjectRepository * CreateObjectRepository(OpenRCT2::IPlatformEnvironment * env);
IObjectRepository * CreateObjectRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
bool IsObjectCustom(const ObjectRepositoryItem * object);

View File

@ -19,6 +19,7 @@
#include "../core/String.hpp"
#include "../localisation/Language.h"
#include "../localisation/LanguagePack.h"
#include "../localisation/LocalisationService.h"
#include "Object.h"
#include "StringTable.h"
@ -100,6 +101,18 @@ std::string StringTable::GetString(uint8 id) const
return std::string();
}
std::string StringTable::GetString(uint8 language, uint8 id) const
{
for (auto &string : _strings)
{
if (string.LanguageId == language && string.Id == id)
{
return string.Text;
}
}
return std::string();
}
void StringTable::SetString(uint8 id, uint8 language, const std::string &text)
{
StringTableEntry entry;
@ -111,7 +124,8 @@ void StringTable::SetString(uint8 id, uint8 language, const std::string &text)
void StringTable::Sort()
{
std::sort(_strings.begin(), _strings.end(), [](const StringTableEntry &a, const StringTableEntry &b) -> bool
auto targetLanguage = LocalisationService_GetCurrentLanguage();
std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry &a, const StringTableEntry &b) -> bool
{
if (a.Id == b.Id)
{
@ -120,11 +134,11 @@ void StringTable::Sort()
return String::Compare(a.Text, b.Text, true) < 0;
}
if (a.LanguageId == gCurrentLanguage)
if (a.LanguageId == targetLanguage)
{
return true;
}
if (b.LanguageId == gCurrentLanguage)
if (b.LanguageId == targetLanguage)
{
return false;
}

View File

@ -56,5 +56,6 @@ public:
void Read(IReadObjectContext * context, IStream * stream, uint8 id);
void Sort();
std::string GetString(uint8 id) const;
std::string GetString(uint8 language, uint8 id) const;
void SetString(uint8 id, uint8 language, const std::string &text);
};

View File

@ -20,6 +20,7 @@
#include "../drawing/Drawing.h"
#include "../interface/Viewport.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "Paint.h"
#include "sprite/Sprite.h"
#include "tile_element/TileElement.h"
@ -1201,7 +1202,7 @@ void paint_draw_money_structs(rct_drawpixelinfo * dpi, paint_string_struct * ps)
// Use sprite font unless the currency contains characters unsupported by the sprite font
bool forceSpriteFont = false;
const currency_descriptor& currencyDesc = CurrencyDescriptors[gConfigGeneral.currency_format];
if (gUseTrueTypeFont && font_supports_string_sprite(currencyDesc.symbol_unicode))
if (LocalisationService_UseTrueTypeFont() && font_supports_string_sprite(currencyDesc.symbol_unicode))
{
forceSpriteFont = true;
}

View File

@ -34,21 +34,21 @@ using namespace OpenRCT2::Drawing;
using namespace OpenRCT2::Paint;
using namespace OpenRCT2::Ui;
Painter::Painter(IUiContext * uiContext)
Painter::Painter(const std::shared_ptr<IUiContext>& uiContext)
: _uiContext(uiContext)
{
}
void Painter::Paint(IDrawingEngine * de)
void Painter::Paint(IDrawingEngine& de)
{
auto dpi = de->GetDrawingPixelInfo();
auto dpi = de.GetDrawingPixelInfo();
if (gIntroState != INTRO_STATE_NONE)
{
intro_draw(dpi);
}
else
{
de->PaintWindows();
de.PaintWindows();
update_palette_effects();
chat_draw(dpi);
@ -62,7 +62,7 @@ void Painter::Paint(IDrawingEngine * de)
gfx_draw_pickedup_peep(dpi);
gfx_invalidate_pickedup_peep();
de->PaintRain();
de.PaintRain();
}
if (gConfigGeneral.show_fps)

View File

@ -38,15 +38,15 @@ namespace OpenRCT2
class Painter final
{
private:
Ui::IUiContext * const _uiContext;
std::shared_ptr<Ui::IUiContext> const _uiContext;
time_t _lastSecond = 0;
sint32 _currentFPS = 0;
sint32 _frames = 0;
public:
explicit Painter(Ui::IUiContext * uiContext);
void Paint(Drawing::IDrawingEngine * de);
explicit Painter(const std::shared_ptr<Ui::IUiContext>& uiContext);
void Paint(Drawing::IDrawingEngine& de);
private:
void PaintFPS(rct_drawpixelinfo * dpi);

View File

@ -26,6 +26,7 @@
#include "../core/FileStream.hpp"
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../localisation/LocalisationService.h"
#include "../object/ObjectRepository.h"
#include "../object/RideObject.h"
#include "../PlatformEnvironment.h"
@ -66,21 +67,21 @@ private:
static constexpr auto PATTERN = "*.td4;*.td6";
public:
explicit TrackDesignFileIndex(IPlatformEnvironment * env) :
explicit TrackDesignFileIndex(const IPlatformEnvironment &env) :
FileIndex("track design index",
MAGIC_NUMBER,
VERSION,
env->GetFilePath(PATHID::CACHE_TRACKS),
env.GetFilePath(PATHID::CACHE_TRACKS),
std::string(PATTERN),
std::vector<std::string>({
env->GetDirectoryPath(DIRBASE::RCT1, DIRID::TRACK),
env->GetDirectoryPath(DIRBASE::RCT2, DIRID::TRACK),
env->GetDirectoryPath(DIRBASE::USER, DIRID::TRACK) }))
env.GetDirectoryPath(DIRBASE::RCT1, DIRID::TRACK),
env.GetDirectoryPath(DIRBASE::RCT2, DIRID::TRACK),
env.GetDirectoryPath(DIRBASE::USER, DIRID::TRACK) }))
{
}
public:
std::tuple<bool, TrackRepositoryItem> Create(const std::string &path) const override
std::tuple<bool, TrackRepositoryItem> Create(sint32, const std::string &path) const override
{
auto td6 = track_design_open(path.c_str());
if (td6 != nullptr)
@ -137,14 +138,14 @@ private:
class TrackDesignRepository final : public ITrackDesignRepository
{
private:
IPlatformEnvironment * const _env;
std::shared_ptr<IPlatformEnvironment> const _env;
TrackDesignFileIndex const _fileIndex;
std::vector<TrackRepositoryItem> _items;
public:
explicit TrackDesignRepository(IPlatformEnvironment * env)
explicit TrackDesignRepository(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env),
_fileIndex(env)
_fileIndex(*env)
{
Guard::ArgumentNotNull(env);
}
@ -284,10 +285,10 @@ public:
return refs;
}
void Scan() override
void Scan(sint32 language) override
{
_items.clear();
auto trackDesigns = _fileIndex.LoadOrBuild();
auto trackDesigns = _fileIndex.LoadOrBuild(language);
for (const auto &td : trackDesigns)
{
_items.push_back(td);
@ -347,7 +348,8 @@ public:
std::string newPath = Path::Combine(installDir, fileName);
if (File::Copy(path, newPath, false))
{
auto td = _fileIndex.Create(path);
auto language = LocalisationService_GetCurrentLanguage();
auto td = _fileIndex.Create(language, path);
if (std::get<0>(td))
{
_items.push_back(std::get<1>(td));
@ -396,7 +398,7 @@ private:
}
};
ITrackDesignRepository * CreateTrackDesignRepository(IPlatformEnvironment * env)
ITrackDesignRepository * CreateTrackDesignRepository(const std::shared_ptr<IPlatformEnvironment>& env)
{
return new TrackDesignRepository(env);
}
@ -404,7 +406,7 @@ ITrackDesignRepository * CreateTrackDesignRepository(IPlatformEnvironment * env)
void track_repository_scan()
{
ITrackDesignRepository * repo = GetContext()->GetTrackDesignRepository();
repo->Scan();
repo->Scan(LocalisationService_GetCurrentLanguage());
}
bool track_repository_delete(const utf8 * path)

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include "../common.h"
#include "RideGroupManager.h"
@ -45,13 +46,13 @@ interface ITrackDesignRepository
virtual std::vector<track_design_file_ref> GetItemsForRideGroup(uint8 rideType,
const RideGroup * rideGroup) const abstract;
virtual void Scan() abstract;
virtual void Scan(sint32 language) abstract;
virtual bool Delete(const std::string &path) abstract;
virtual std::string Rename(const std::string &path, const std::string &newName) abstract;
virtual std::string Install(const std::string &path) abstract;
};
ITrackDesignRepository * CreateTrackDesignRepository(OpenRCT2::IPlatformEnvironment * env);
ITrackDesignRepository * CreateTrackDesignRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
std::string GetNameFromTrackPath(const std::string &path);
void track_repository_scan();

View File

@ -33,6 +33,7 @@
#include "../config/Config.h"
#include "../localisation/Localisation.h"
#include "../localisation/LocalisationService.h"
#include "../platform/platform.h"
#include "Scenario.h"
#include "../Game.h"
@ -128,21 +129,21 @@ private:
static constexpr auto PATTERN = "*.sc4;*.sc6";
public:
explicit ScenarioFileIndex(IPlatformEnvironment * env) :
explicit ScenarioFileIndex(const IPlatformEnvironment& env) :
FileIndex("scenario index",
MAGIC_NUMBER,
VERSION,
env->GetFilePath(PATHID::CACHE_SCENARIOS),
env.GetFilePath(PATHID::CACHE_SCENARIOS),
std::string(PATTERN),
std::vector<std::string>({
env->GetDirectoryPath(DIRBASE::RCT1, DIRID::SCENARIO),
env->GetDirectoryPath(DIRBASE::RCT2, DIRID::SCENARIO),
env->GetDirectoryPath(DIRBASE::USER, DIRID::SCENARIO) }))
env.GetDirectoryPath(DIRBASE::RCT1, DIRID::SCENARIO),
env.GetDirectoryPath(DIRBASE::RCT2, DIRID::SCENARIO),
env.GetDirectoryPath(DIRBASE::USER, DIRID::SCENARIO) }))
{
}
protected:
std::tuple<bool, scenario_index_entry> Create(const std::string &path) const override
std::tuple<bool, scenario_index_entry> Create(sint32, const std::string &path) const override
{
scenario_index_entry entry;
auto timestamp = File::GetLastModified(path);
@ -322,15 +323,15 @@ class ScenarioRepository final : public IScenarioRepository
private:
static constexpr uint32 HighscoreFileVersion = 1;
IPlatformEnvironment * const _env;
std::shared_ptr<IPlatformEnvironment> const _env;
ScenarioFileIndex const _fileIndex;
std::vector<scenario_index_entry> _scenarios;
std::vector<scenario_highscore_entry*> _highscores;
public:
explicit ScenarioRepository(IPlatformEnvironment * env)
explicit ScenarioRepository(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env),
_fileIndex(env)
_fileIndex(*env)
{
}
@ -339,13 +340,13 @@ public:
ClearHighscores();
}
void Scan() override
void Scan(sint32 language) override
{
ImportMegaPark();
// Reload scenarios from index
_scenarios.clear();
auto scenarios = _fileIndex.LoadOrBuild();
auto scenarios = _fileIndex.LoadOrBuild(language);
for (auto scenario : scenarios)
{
AddScenario(scenario);
@ -415,11 +416,11 @@ public:
return nullptr;
}
bool TryRecordHighscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) override
bool TryRecordHighscore(sint32 language, const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) override
{
// Scan the scenarios so we have a fresh list to query. This is to prevent the issue of scenario completions
// not getting recorded, see #4951.
Scan();
Scan(language);
scenario_index_entry * scenario = GetByFilename(scenarioFileName);
if (scenario != nullptr)
@ -729,7 +730,7 @@ private:
static ScenarioRepository * _scenarioRepository;
IScenarioRepository * CreateScenarioRepository(IPlatformEnvironment * env)
IScenarioRepository * CreateScenarioRepository(const std::shared_ptr<IPlatformEnvironment>& env)
{
_scenarioRepository = new ScenarioRepository(env);
return _scenarioRepository;
@ -743,7 +744,7 @@ IScenarioRepository * GetScenarioRepository()
void scenario_repository_scan()
{
IScenarioRepository * repo = GetScenarioRepository();
repo->Scan();
repo->Scan(LocalisationService_GetCurrentLanguage());
}
size_t scenario_repository_get_count()
@ -761,6 +762,6 @@ const scenario_index_entry *scenario_repository_get_by_index(size_t index)
bool scenario_repository_try_record_highscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name)
{
IScenarioRepository * repo = GetScenarioRepository();
return repo->TryRecordHighscore(scenarioFileName, companyValue, name);
return repo->TryRecordHighscore(LocalisationService_GetCurrentLanguage(), scenarioFileName, companyValue, name);
}

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include "../common.h"
struct rct_object_entry;
@ -63,7 +64,7 @@ interface IScenarioRepository
/**
* Scans the scenario directories and grabs the metadata for all the scenarios.
*/
virtual void Scan() abstract;
virtual void Scan(sint32 language) abstract;
virtual size_t GetCount() const abstract;
virtual const scenario_index_entry * GetByIndex(size_t index) const abstract;
@ -74,10 +75,10 @@ interface IScenarioRepository
virtual const scenario_index_entry * GetByInternalName(const utf8 * name) const abstract;
virtual const scenario_index_entry * GetByPath(const utf8 * path) const abstract;
virtual bool TryRecordHighscore(const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) abstract;
virtual bool TryRecordHighscore(sint32 language, const utf8 * scenarioFileName, money32 companyValue, const utf8 * name) abstract;
};
IScenarioRepository * CreateScenarioRepository(OpenRCT2::IPlatformEnvironment * env);
IScenarioRepository * CreateScenarioRepository(const std::shared_ptr<OpenRCT2::IPlatformEnvironment>& env);
IScenarioRepository * GetScenarioRepository();
void scenario_repository_scan();

View File

@ -66,10 +66,18 @@ namespace OpenRCT2::Ui
const uint8 * GetKeysPressed() override { return nullptr; }
void SetKeysPressed(uint32 keysym, uint8 scancode) override { }
// Drawing
Drawing::IDrawingEngine * CreateDrawingEngine(Drawing::DRAWING_ENGINE_TYPE type) override
class X8DrawingEngineFactory final : public IDrawingEngineFactory
{
return new X8DrawingEngine(this);
std::unique_ptr<IDrawingEngine> Create(DRAWING_ENGINE_TYPE type, const std::shared_ptr<IUiContext>& uiContext) override
{
return std::make_unique<X8DrawingEngine>(uiContext);
}
};
// Drawing
std::shared_ptr<IDrawingEngineFactory> GetDrawingEngineFactory() override
{
return std::make_shared<X8DrawingEngineFactory>();
}
// Text input
@ -92,8 +100,8 @@ namespace OpenRCT2::Ui
~DummyUiContext() { delete _windowManager; }
};
IUiContext * CreateDummyUiContext()
std::shared_ptr<IUiContext> CreateDummyUiContext()
{
return new DummyUiContext();
return std::make_unique<DummyUiContext>();
}
} // namespace OpenRCT2::Ui

View File

@ -16,6 +16,7 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "../common.h"
@ -28,8 +29,7 @@ namespace OpenRCT2
{
namespace Drawing
{
enum class DRAWING_ENGINE_TYPE;
interface IDrawingEngine;
interface IDrawingEngineFactory;
} // namespace Drawing
namespace Ui
@ -130,7 +130,7 @@ namespace OpenRCT2
virtual void SetKeysPressed(uint32 keysym, uint8 scancode) abstract;
// Drawing
virtual Drawing::IDrawingEngine * CreateDrawingEngine(Drawing::DRAWING_ENGINE_TYPE type) abstract;
virtual std::shared_ptr<Drawing::IDrawingEngineFactory> GetDrawingEngineFactory() abstract;
// Text input
virtual bool IsTextInputActive() abstract;
@ -149,6 +149,6 @@ namespace OpenRCT2
virtual bool SetClipboardText(const utf8* target) abstract;
};
IUiContext * CreateDummyUiContext();
std::shared_ptr<IUiContext> CreateDummyUiContext();
} // namespace Ui
} // namespace OpenRCT2

View File

@ -46,8 +46,6 @@ TEST(MultiLaunchTest, all)
// Check ride count again
ASSERT_EQ(gRideCount, 134);
delete context;
}
SUCCEED();
}

View File

@ -91,6 +91,4 @@ TEST_F(RideRatings, all)
expI++;
}
}
delete context;
}

View File

@ -27,19 +27,11 @@ protected:
game_load_init();
SUCCEED();
}
static void TearDownTestCase()
{
delete _context;
_context = nullptr;
SUCCEED();
}
private:
static IContext * _context;
static std::shared_ptr<IContext> _context;
};
IContext * TileElementWantsFootpathConnection::_context = nullptr;
std::shared_ptr<IContext> TileElementWantsFootpathConnection::_context;
TEST_F(TileElementWantsFootpathConnection, FlatPath)
{