OpenRCT2/src/openrct2/Context.cpp

1222 lines
38 KiB
C++
Raw Normal View History

#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
2018-02-01 13:52:39 +01:00
#include <algorithm>
2018-03-14 15:25:34 +01:00
#include <cmath>
#include <exception>
#include <memory>
#include <string>
2017-09-04 23:17:35 +02:00
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif // __EMSCRIPTEN__
#include "audio/AudioContext.h"
#include "Context.h"
#include "ui/UiContext.h"
#include "core/Console.hpp"
#include "core/File.h"
#include "core/FileScanner.h"
#include "core/FileStream.hpp"
#include "core/Guard.hpp"
#include "core/Math.hpp"
#include "core/MemoryStream.h"
#include "core/Path.hpp"
#include "core/String.hpp"
#include "core/Util.hpp"
#include "FileClassifier.h"
2018-03-21 10:42:51 +01:00
#include "HandleParkLoad.h"
#include "network/network.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
#include "OpenRCT2.h"
#include "ParkImporter.h"
2018-01-18 13:55:34 +01:00
#include "platform/Crash.h"
#include "PlatformEnvironment.h"
#include "ride/TrackDesignRepository.h"
2018-03-19 23:28:40 +01:00
#include "scenario/Scenario.h"
#include "scenario/ScenarioRepository.h"
#include "title/TitleScreen.h"
#include "title/TitleSequenceManager.h"
#include "ui/WindowManager.h"
#include "Version.h"
#include "audio/audio.h"
#include "config/Config.h"
2018-01-05 22:11:19 +01:00
#include "drawing/LightFX.h"
#include "Editor.h"
2017-11-30 18:17:06 +01:00
#include "Game.h"
2017-12-12 14:52:57 +01:00
#include "Input.h"
2018-01-06 00:00:39 +01:00
#include "interface/Chat.h"
2018-01-06 00:28:04 +01:00
#include "interface/Console.h"
#include "interface/themes.h"
#include "interface/Viewport.h"
2017-12-12 14:52:57 +01:00
#include "Intro.h"
2018-01-06 18:32:25 +01:00
#include "localisation/Date.h"
#include "localisation/Language.h"
2017-11-10 21:23:23 +01:00
#include "network/DiscordService.h"
#include "network/http.h"
#include "network/network.h"
#include "network/twitch.h"
#include "platform/platform.h"
2017-12-13 13:02:24 +01:00
#include "util/Util.h"
using namespace OpenRCT2;
2017-03-28 20:58:15 +02:00
using namespace OpenRCT2::Audio;
using namespace OpenRCT2::Ui;
namespace OpenRCT2
{
class Context : public IContext
{
private:
// Dependencies
IPlatformEnvironment * const _env = nullptr;
IAudioContext * const _audioContext = nullptr;
IUiContext * const _uiContext = nullptr;
// Services
IObjectRepository * _objectRepository = nullptr;
IObjectManager * _objectManager = nullptr;
ITrackDesignRepository * _trackDesignRepository = nullptr;
IScenarioRepository * _scenarioRepository = nullptr;
2017-11-10 21:23:23 +01:00
#ifdef __ENABLE_DISCORD__
DiscordService * _discordService = nullptr;
#endif
StdInOutConsole _stdInOutConsole;
2017-07-23 00:42:14 +02:00
// Game states
TitleScreen * _titleScreen = nullptr;
bool _initialised = false;
2017-06-26 00:45:19 +02:00
bool _isWindowMinimised = false;
uint32 _lastTick = 0;
uint32 _accumulator = 0;
uint32 _lastUpdateTick = 0;
bool _variableFrame = false;
/** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to false. */
bool _finished = false;
public:
// Singleton of Context.
// Remove this when GetContext() is no longer called so that
// multiple instances can be created in parallel
static Context * Instance;
public:
2017-06-11 13:53:37 +02:00
Context(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
: _env(env),
_audioContext(audioContext),
2017-03-28 20:58:15 +02:00
_uiContext(uiContext)
{
Instance = this;
}
~Context() override
{
window_close_all();
http_dispose();
language_close_all();
object_manager_unload_all_objects();
gfx_object_check_all_images_freed();
gfx_unload_g2();
gfx_unload_g1();
config_release();
#ifndef DISABLE_NETWORK
EVP_MD_CTX_destroy(gHashCTX);
#endif // DISABLE_NETWORK
2017-07-23 00:42:14 +02:00
delete _titleScreen;
2017-11-10 21:23:23 +01:00
#ifdef __ENABLE_DISCORD__
delete _discordService;
#endif
delete _scenarioRepository;
delete _trackDesignRepository;
delete _objectManager;
delete _objectRepository;
Instance = nullptr;
}
2017-03-28 20:58:15 +02:00
IAudioContext * GetAudioContext() override
{
return _audioContext;
}
IUiContext * GetUiContext() override
{
return _uiContext;
}
IPlatformEnvironment * GetPlatformEnvironment() override
{
return _env;
}
IObjectManager * GetObjectManager() override
{
return _objectManager;
}
IObjectRepository * GetObjectRepository() override
{
return _objectRepository;
}
ITrackDesignRepository * GetTrackDesignRepository() override
{
return _trackDesignRepository;
}
IScenarioRepository * GetScenarioRepository() override
{
return _scenarioRepository;
}
2017-10-17 00:04:40 +02:00
sint32 RunOpenRCT2(int argc, const char * * argv) override
{
if (Initialise())
{
Launch();
}
return gExitCode;
}
2018-03-11 23:25:34 +01:00
void WriteLine(const std::string &s) override
{
_stdInOutConsole.WriteLine(s);
}
/**
* Causes the OpenRCT2 game loop to finish.
*/
2017-05-06 22:53:51 +02:00
void Finish() override
{
_finished = true;
}
2017-07-28 19:43:48 +02:00
void Quit() override
{
gSavePromptMode = PM_QUIT;
2017-08-06 05:22:00 +02:00
context_open_window(WC_SAVE_PROMPT);
2017-07-28 19:43:48 +02:00
}
std::string GetPathLegacy(sint32 pathId) override
{
static constexpr const char * const LegacyFileNames[PATH_ID_END] =
{
nullptr,
nullptr,
"css1.dat",
"css2.dat",
"css4.dat",
"css5.dat",
"css6.dat",
"css7.dat",
"css8.dat",
"css9.dat",
"css11.dat",
"css12.dat",
"css13.dat",
"css14.dat",
"css15.dat",
"css3.dat",
"css17.dat",
"css18.dat",
"css19.dat",
"css20.dat",
"css21.dat",
"css22.dat",
nullptr,
"css23.dat",
"css24.dat",
"css25.dat",
"css26.dat",
"css27.dat",
"css28.dat",
"css29.dat",
"css30.dat",
"css31.dat",
"css32.dat",
"css33.dat",
"css34.dat",
"css35.dat",
"css36.dat",
"css37.dat",
"css38.dat",
"CUSTOM1.WAV",
"CUSTOM2.WAV",
"css39.dat",
"css40.dat",
"css41.dat",
nullptr,
"css42.dat",
"css43.dat",
"css44.dat",
"css45.dat",
"css46.dat",
"css50.dat"
};
std::string result;
if (pathId == PATH_ID_CSS50)
{
auto dataPath = _env->GetDirectoryPath(DIRBASE::RCT1, DIRID::DATA);
result = Path::Combine(dataPath, "css17.dat");
}
else if (pathId >= 0 && pathId < PATH_ID_END)
{
auto fileName = LegacyFileNames[pathId];
if (fileName != nullptr)
{
auto dataPath = _env->GetDirectoryPath(DIRBASE::RCT2, DIRID::DATA);
result = Path::Combine(dataPath, fileName);
}
}
return result;
}
bool Initialise() final override
{
if (_initialised)
{
throw std::runtime_error("Context already initialised.");
}
_initialised = true;
#ifndef DISABLE_NETWORK
gHashCTX = EVP_MD_CTX_create();
Guard::Assert(gHashCTX != nullptr, "EVP_MD_CTX_create failed");
#endif // DISABLE_NETWORK
crash_init();
if (gConfigGeneral.last_run_version != nullptr && String::Equals(gConfigGeneral.last_run_version, OPENRCT2_VERSION))
{
gOpenRCT2ShowChangelog = false;
}
else
{
gOpenRCT2ShowChangelog = true;
gConfigGeneral.last_run_version = String::Duplicate(OPENRCT2_VERSION);
config_save_default();
}
// TODO add configuration option to allow multiple instances
// if (!gOpenRCT2Headless && !platform_lock_single_instance()) {
// log_fatal("OpenRCT2 is already running.");
// return false;
// } //This comment was relocated so it would stay where it was in relation to the following lines of code.
if (!gOpenRCT2Headless)
{
auto rct2InstallPath = GetOrPromptRCT2Path();
if (rct2InstallPath.empty())
{
return false;
}
_env->SetBasePath(DIRBASE::RCT2, rct2InstallPath);
}
_objectRepository = CreateObjectRepository(_env);
_objectManager = CreateObjectManager(_objectRepository);
_trackDesignRepository = CreateTrackDesignRepository(_env);
_scenarioRepository = CreateScenarioRepository(_env);
2017-11-10 21:23:23 +01:00
#ifdef __ENABLE_DISCORD__
_discordService = new DiscordService();
#endif
if (!language_open(gConfigGeneral.language))
{
log_error("Failed to open configured language...");
if (!language_open(LANGUAGE_ENGLISH_UK))
{
log_fatal("Failed to open fallback language...");
return false;
}
}
if (platform_process_is_elevated())
{
std::string elevationWarning = language_get_string(STR_ADMIN_NOT_RECOMMENDED);
if (gOpenRCT2Headless)
{
Console::Error::WriteLine(elevationWarning.c_str());
}
else
{
_uiContext->ShowMessageBox(elevationWarning);
}
}
if (!gOpenRCT2Headless)
{
2017-06-26 00:45:19 +02:00
_uiContext->CreateWindow();
}
// 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();
// 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();
_scenarioRepository->Scan();
TitleSequenceManager::Scan();
if (!gOpenRCT2Headless)
{
audio_init();
audio_populate_devices();
audio_init_ride_sounds_and_info();
}
http_init();
2017-06-06 18:55:13 +02:00
network_set_env(_env);
chat_init();
theme_manager_initialise();
CopyOriginalUserFilesOver();
if (!gOpenRCT2NoGraphics)
{
if (!LoadBaseGraphics())
{
return false;
}
#ifdef __ENABLE_LIGHTFX__
lightfx_init();
#endif
}
gScenarioTicks = 0;
2017-10-03 00:00:32 +02:00
util_srand((uint32)time(nullptr));
input_reset_place_obj_modifier();
viewport_init_all();
game_init_all(150);
2017-07-23 00:42:14 +02:00
_titleScreen = new TitleScreen();
return true;
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
bool LoadParkFromFile(const std::string &path, bool loadTitleScreenOnFail) final override
2017-07-02 20:10:22 +02:00
{
try
{
auto fs = FileStream(path, FILE_MODE_OPEN);
return LoadParkFromStream(&fs, path, loadTitleScreenOnFail);
}
catch (const std::exception &e)
{
Console::Error::WriteLine(e.what());
}
return false;
2017-07-02 20:10:22 +02:00
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
bool LoadParkFromStream(IStream * stream, const std::string &path, bool loadTitleScreenFirstOnFail) final override
{
ClassifiedFileInfo info;
if (TryClassifyFile(stream, &info))
{
if (info.Type == FILE_TYPE::SAVED_GAME ||
info.Type == FILE_TYPE::SCENARIO)
{
std::unique_ptr<IParkImporter> parkImporter;
if (info.Version <= FILE_TYPE_S4_CUTOFF)
{
// Save is an S4 (RCT1 format)
parkImporter.reset(ParkImporter::CreateS4());
}
else
{
// Save is an S6 (RCT2 format)
parkImporter.reset(ParkImporter::CreateS6(_objectRepository, _objectManager));
}
try
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
auto result = parkImporter->LoadFromStream(stream, info.Type == FILE_TYPE::SCENARIO, false, path.c_str());
if (result.Error == PARK_LOAD_ERROR_OK)
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
parkImporter->Import();
String::Set(gScenarioSavePath, Util::CountOf(gScenarioSavePath), path.c_str());
String::Set(gCurrentLoadedPath, Util::CountOf(gCurrentLoadedPath), path.c_str());
gFirstTimeSaving = true;
game_fix_save_vars();
sprite_position_tween_reset();
gScreenAge = 0;
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
if (info.Type == FILE_TYPE::SAVED_GAME)
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
if (network_get_mode() == NETWORK_MODE_CLIENT)
{
network_close();
}
game_load_init();
if (network_get_mode() == NETWORK_MODE_SERVER)
{
network_send_map();
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
else
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
scenario_begin();
if (network_get_mode() == NETWORK_MODE_SERVER)
{
network_send_map();
}
if (network_get_mode() == NETWORK_MODE_CLIENT)
{
network_close();
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
// This ensures that the newly loaded save reflects the user's
// 'show real names of guests' option, now that it's a global setting
peep_update_names(gConfigGeneral.show_real_names_of_guests);
return true;
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
else
{
2018-02-07 21:51:09 +01:00
handle_park_load_failure_with_title_opt(&result, path, loadTitleScreenFirstOnFail);
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
}
2018-01-02 20:23:22 +01:00
catch (const std::exception &e)
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
2018-01-02 20:23:22 +01:00
Console::Error::WriteLine(e.what());
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
}
else
{
Console::Error::WriteLine("Invalid file type.");
}
}
else
{
Console::Error::WriteLine("Unable to detect file type.");
}
return false;
}
private:
std::string GetOrPromptRCT2Path()
{
auto result = std::string();
if (String::IsNullOrEmpty(gCustomRCT2DataPath))
{
// Check install directory
if (gConfigGeneral.rct2_path == nullptr || !platform_original_game_data_exists(gConfigGeneral.rct2_path))
{
log_verbose("install directory does not exist or invalid directory selected, %s", gConfigGeneral.rct2_path);
if (!config_find_or_browse_install_directory())
{
utf8 path[MAX_PATH];
config_get_default_path(path, sizeof(path));
Console::Error::WriteLine("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.\n", path);
return std::string();
}
}
result = std::string(gConfigGeneral.rct2_path);
}
else
{
result = std::string(gCustomRCT2DataPath);
}
return result;
}
bool LoadBaseGraphics()
{
if (!gfx_load_g1(_env))
{
return false;
}
2018-02-05 19:26:27 +01:00
gfx_load_g2();
gfx_load_csg();
font_sprite_initialise_characters();
return true;
}
/**
* Launches the game, after command line arguments have been parsed and processed.
*/
void Launch()
{
gIntroState = INTRO_STATE_NONE;
if ((gOpenRCT2StartupAction == STARTUP_ACTION_TITLE) && gConfigGeneral.play_intro)
{
gOpenRCT2StartupAction = STARTUP_ACTION_INTRO;
}
switch (gOpenRCT2StartupAction) {
case STARTUP_ACTION_INTRO:
gIntroState = INTRO_STATE_PUBLISHER_BEGIN;
title_load();
break;
case STARTUP_ACTION_TITLE:
title_load();
break;
case STARTUP_ACTION_OPEN:
{
// A path that includes "://" is illegal with all common filesystems, so it is almost certainly a URL
// This way all cURL supported protocols, like http, ftp, scp and smb are automatically handled
if (strstr(gOpenRCT2StartupActionPath, "://") != nullptr)
{
#ifndef DISABLE_HTTP
// Download park and open it using its temporary filename
void * data;
size_t dataSize = http_download_park(gOpenRCT2StartupActionPath, &data);
if (dataSize == 0)
{
title_load();
break;
}
auto ms = MemoryStream(data, dataSize, MEMORY_ACCESS::OWNER);
if (!LoadParkFromStream(&ms, gOpenRCT2StartupActionPath, true))
2017-07-02 20:10:22 +02:00
{
Console::Error::WriteLine("Failed to load '%s'", gOpenRCT2StartupActionPath);
title_load();
break;
}
#endif
}
else
{
2017-07-02 20:10:22 +02:00
try
{
if (!LoadParkFromFile(gOpenRCT2StartupActionPath, true))
{
break;
}
2017-07-02 20:10:22 +02:00
}
catch (const std::exception &ex)
{
Console::Error::WriteLine("Failed to load '%s'", gOpenRCT2StartupActionPath);
Console::Error::WriteLine("%s", ex.what());
title_load();
break;
}
}
gScreenFlags = SCREEN_FLAGS_PLAYING;
#ifndef DISABLE_NETWORK
if (gNetworkStart == NETWORK_MODE_SERVER)
{
if (gNetworkStartPort == 0)
{
gNetworkStartPort = gConfigNetwork.default_port;
}
if (String::IsNullOrEmpty(gNetworkStartAddress))
{
gNetworkStartAddress = gConfigNetwork.listen_address;
}
if (String::IsNullOrEmpty(gCustomPassword))
{
network_set_password(gConfigNetwork.default_password);
}
else
{
network_set_password(gCustomPassword);
}
network_begin_server(gNetworkStartPort, gNetworkStartAddress);
}
#endif // DISABLE_NETWORK
break;
}
case STARTUP_ACTION_EDIT:
if (String::SizeOf(gOpenRCT2StartupActionPath) == 0)
{
Editor::Load();
}
else if (!Editor::LoadLandscape(gOpenRCT2StartupActionPath))
{
title_load();
}
break;
}
#ifndef DISABLE_NETWORK
if (gNetworkStart == NETWORK_MODE_CLIENT)
{
if (gNetworkStartPort == 0)
{
gNetworkStartPort = gConfigNetwork.default_port;
}
network_begin_client(gNetworkStartHost, gNetworkStartPort);
}
#endif // DISABLE_NETWORK
// For now, only allow interactive console in headless mode
if (gOpenRCT2Headless)
{
_stdInOutConsole.Start();
}
RunGameLoop();
}
bool ShouldRunVariableFrame()
{
if (!gConfigGeneral.uncap_fps) return false;
if (gGameSpeed > 4) return false;
if (gOpenRCT2Headless) return false;
if (_uiContext->IsMinimised()) return false;
return true;
}
/**
* Run the main game loop until the finished flag is set.
*/
void RunGameLoop()
{
log_verbose("begin openrct2 loop");
_finished = false;
2017-09-04 23:17:35 +02:00
#ifndef __EMSCRIPTEN__
_variableFrame = ShouldRunVariableFrame();
do
{
2017-09-07 13:31:28 +02:00
RunFrame();
}
while (!_finished);
2017-09-04 23:17:35 +02:00
#else
emscripten_set_main_loop_arg([](void * vctx) ->
{
auto ctx = reinterpret_cast<Context *>(vctx);
ctx->RunFrame();
}, this, 0, 1);
2017-09-04 23:17:35 +02:00
#endif // __EMSCRIPTEN__
log_verbose("finish openrct2 loop");
}
void RunFrame()
{
// Make sure we catch the state change and reset it.
bool useVariableFrame = ShouldRunVariableFrame();
if (_variableFrame != useVariableFrame)
{
_lastTick = 0;
_variableFrame = useVariableFrame;
}
if (useVariableFrame)
{
RunVariableFrame();
}
else
{
RunFixedFrame();
}
}
void RunFixedFrame()
{
uint32 currentTick = platform_get_ticks();
if (_lastTick == 0)
{
_lastTick = currentTick;
}
uint32 elapsed = currentTick - _lastTick;
_lastTick = currentTick;
_accumulator = Math::Min(_accumulator + elapsed, (uint32)GAME_UPDATE_MAX_THRESHOLD);
2017-06-26 00:45:19 +02:00
_uiContext->ProcessMessages();
if (_accumulator < GAME_UPDATE_TIME_MS)
{
platform_sleep(GAME_UPDATE_TIME_MS - _accumulator - 1);
return;
}
_accumulator -= GAME_UPDATE_TIME_MS;
2017-06-26 00:45:19 +02:00
Update();
if (!_isWindowMinimised && !gOpenRCT2Headless)
{
drawing_engine_draw();
}
}
void RunVariableFrame()
{
uint32 currentTick = platform_get_ticks();
bool draw = !_isWindowMinimised && !gOpenRCT2Headless;
if (_lastTick == 0)
{
sprite_position_tween_reset();
_lastTick = currentTick;
}
uint32 elapsed = currentTick - _lastTick;
_lastTick = currentTick;
_accumulator = Math::Min(_accumulator + elapsed, (uint32)GAME_UPDATE_MAX_THRESHOLD);
2017-06-26 00:45:19 +02:00
_uiContext->ProcessMessages();
while (_accumulator >= GAME_UPDATE_TIME_MS)
{
// Get the original position of each sprite
if(draw)
sprite_position_tween_store_a();
2017-06-26 00:45:19 +02:00
Update();
_accumulator -= GAME_UPDATE_TIME_MS;
// Get the next position of each sprite
if(draw)
sprite_position_tween_store_b();
}
if (draw)
{
const float alpha = (float)_accumulator / GAME_UPDATE_TIME_MS;
sprite_position_tween_all(alpha);
drawing_engine_draw();
sprite_position_tween_restore();
}
}
2017-06-26 00:45:19 +02:00
void Update()
{
uint32 currentUpdateTick = platform_get_ticks();
gTicksSinceLastUpdate = std::min<uint32>(currentUpdateTick - _lastUpdateTick, 500);
_lastUpdateTick = currentUpdateTick;
2017-06-26 00:45:19 +02:00
if (game_is_not_paused())
{
gPaletteEffectFrame += gTicksSinceLastUpdate;
}
date_update_real_time_of_day();
if (gIntroState != INTRO_STATE_NONE)
{
intro_update();
}
else if ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) && !gOpenRCT2Headless)
{
2017-07-23 00:42:14 +02:00
_titleScreen->Update();
2017-06-26 00:45:19 +02:00
}
else
{
game_update();
}
2017-11-10 21:23:23 +01:00
#ifdef __ENABLE_DISCORD__
if (_discordService != nullptr)
{
_discordService->Update();
}
#endif
2017-06-26 00:45:19 +02:00
twitch_update();
chat_update();
_stdInOutConsole.ProcessEvalQueue();
2018-03-11 23:25:34 +01:00
_uiContext->Update();
2017-06-26 00:45:19 +02:00
}
/**
* Copy saved games and landscapes to user directory
*/
void CopyOriginalUserFilesOver()
{
CopyOriginalUserFilesOver(DIRID::SAVE, "*.sv6");
CopyOriginalUserFilesOver(DIRID::LANDSCAPE, "*.sc6");
}
void CopyOriginalUserFilesOver(DIRID dirid, const std::string &pattern)
{
auto src = _env->GetDirectoryPath(DIRBASE::RCT2, dirid);
auto dst = _env->GetDirectoryPath(DIRBASE::USER, dirid);
CopyOriginalUserFilesOver(src, dst, pattern);
}
void CopyOriginalUserFilesOver(const std::string &srcRoot, const std::string &dstRoot, const std::string &pattern)
{
log_verbose("CopyOriginalUserFilesOver('%s', '%s', '%s')", srcRoot.c_str(), dstRoot.c_str(), pattern.c_str());
auto scanPattern = Path::Combine(srcRoot, pattern);
auto scanner = Path::ScanDirectory(scanPattern, true);
while (scanner->Next())
{
auto src = std::string(scanner->GetPath());
auto dst = Path::Combine(dstRoot, scanner->GetPathRelative());
auto dstDirectory = Path::GetDirectory(dst);
// Create the directory if necessary
if (!platform_directory_exists(dstDirectory.c_str()))
{
Console::WriteLine("Creating directory '%s'", dstDirectory.c_str());
if (!platform_ensure_directory_exists(dstDirectory.c_str()))
{
Console::Error::WriteLine("Could not create directory %s.", dstDirectory.c_str());
break;
}
}
// Only copy the file if it doesn't already exist
if (!File::Exists(dst))
{
Console::WriteLine("Copying '%s' to '%s'", src.c_str(), dst.c_str());
if (!File::Copy(src, dst, false))
{
Console::Error::WriteLine("Failed to copy '%s' to '%s'", src.c_str(), dst.c_str());
}
}
}
delete scanner;
}
};
class PlainContext final : public Context
{
2017-06-11 13:53:37 +02:00
std::unique_ptr<IPlatformEnvironment> _env;
std::unique_ptr<IAudioContext> _audioContext;
std::unique_ptr<IUiContext> _uiContext;
public:
PlainContext()
2017-06-11 13:53:37 +02:00
: PlainContext(CreatePlatformEnvironment(), CreateDummyAudioContext(), CreateDummyUiContext())
{
}
2017-06-11 13:53:37 +02:00
PlainContext(IPlatformEnvironment * env, IAudioContext * audioContext, IUiContext * uiContext)
: Context(env, audioContext, uiContext)
{
2017-06-11 13:53:37 +02:00
_env = std::unique_ptr<IPlatformEnvironment>(env);
_audioContext = std::unique_ptr<IAudioContext>(audioContext);
_uiContext = std::unique_ptr<IUiContext>(uiContext);
}
};
Context * Context::Instance = nullptr;
IContext * CreateContext()
{
return new PlainContext();
}
2017-06-11 13:53:37 +02:00
IContext * CreateContext(IPlatformEnvironment * env, Audio::IAudioContext * audioContext, IUiContext * uiContext)
{
2017-06-11 13:53:37 +02:00
return new Context(env, audioContext, uiContext);
}
IContext * GetContext()
{
return Context::Instance;
}
}
2018-02-01 18:49:14 +01:00
void context_init()
{
2018-02-01 18:49:14 +01:00
GetContext()->GetUiContext()->GetWindowManager()->Init();
}
2017-09-10 11:02:16 +02:00
2018-02-01 18:49:14 +01:00
bool context_load_park_from_file(const utf8 * path)
{
return GetContext()->LoadParkFromFile(path);
}
2018-02-01 18:49:14 +01:00
bool context_load_park_from_stream(void * stream)
{
return GetContext()->LoadParkFromStream((IStream*)stream, "");
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
2018-02-01 18:49:14 +01:00
void openrct2_write_full_version_info(utf8 * buffer, size_t bufferSize)
{
String::Set(buffer, bufferSize, gVersionInfoFull);
}
2018-02-01 18:49:14 +01:00
void openrct2_finish()
{
GetContext()->Finish();
}
2018-02-01 18:49:14 +01:00
void context_setcurrentcursor(sint32 cursor)
{
GetContext()->GetUiContext()->SetCursor((CURSOR_ID)cursor);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_update_cursor_scale()
{
2018-03-14 15:25:34 +01:00
GetContext()->GetUiContext()->SetCursorScale(static_cast<uint8>(std::round(gConfigGeneral.window_scale)));
2018-02-01 18:49:14 +01:00
}
2017-12-09 17:08:38 +01:00
2018-02-01 18:49:14 +01:00
void context_hide_cursor()
{
GetContext()->GetUiContext()->SetCursorVisible(false);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_show_cursor()
{
GetContext()->GetUiContext()->SetCursorVisible(true);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_get_cursor_position(sint32 * x, sint32 * y)
{
GetContext()->GetUiContext()->GetCursorPosition(x, y);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_get_cursor_position_scaled(sint32 * x, sint32 * y)
{
context_get_cursor_position(x, y);
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
// Compensate for window scaling.
2018-03-14 15:25:34 +01:00
*x = (sint32)std::ceil(*x / gConfigGeneral.window_scale);
*y = (sint32)std::ceil(*y / gConfigGeneral.window_scale);
2018-02-01 18:49:14 +01:00
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_set_cursor_position(sint32 x, sint32 y)
{
GetContext()->GetUiContext()->SetCursorPosition(x, y);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
const CursorState * context_get_cursor_state()
{
return GetContext()->GetUiContext()->GetCursorState();
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
const uint8 * context_get_keys_state()
{
return GetContext()->GetUiContext()->GetKeysState();
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
const uint8 * context_get_keys_pressed()
{
return GetContext()->GetUiContext()->GetKeysPressed();
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
TextInputSession * context_start_text_input(utf8 * buffer, size_t maxLength)
{
return GetContext()->GetUiContext()->StartTextInput(buffer, maxLength);
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
void context_stop_text_input()
{
GetContext()->GetUiContext()->StopTextInput();
}
2017-03-25 18:42:14 +01:00
2018-02-01 18:49:14 +01:00
bool context_is_input_active()
{
return GetContext()->GetUiContext()->IsTextInputActive();
}
2017-03-26 04:36:22 +02:00
2018-02-01 18:49:14 +01:00
void context_trigger_resize()
{
return GetContext()->GetUiContext()->TriggerResize();
}
2017-03-26 04:36:22 +02:00
2018-02-01 18:49:14 +01:00
void context_set_fullscreen_mode(sint32 mode)
{
return GetContext()->GetUiContext()->SetFullscreenMode((FULLSCREEN_MODE)mode);
}
2017-03-26 04:36:22 +02:00
2018-02-01 18:49:14 +01:00
void context_recreate_window()
{
GetContext()->GetUiContext()->RecreateWindow();
}
2018-02-01 18:49:14 +01:00
sint32 context_get_resolutions(Resolution * * outResolutions)
{
auto resolutions = GetContext()->GetUiContext()->GetFullscreenResolutions();
sint32 count = (sint32)resolutions.size();
*outResolutions = Memory::AllocateArray<Resolution>(count);
std::copy_n(resolutions.begin(), count, *outResolutions);
return count;
}
2018-02-01 18:49:14 +01:00
sint32 context_get_width()
{
return GetContext()->GetUiContext()->GetWidth();
}
2018-02-01 18:49:14 +01:00
sint32 context_get_height()
{
return GetContext()->GetUiContext()->GetHeight();
}
2017-04-01 14:38:52 +02:00
2018-02-01 18:49:14 +01:00
bool context_has_focus()
{
return GetContext()->GetUiContext()->HasFocus();
}
2017-04-01 14:38:52 +02:00
2018-02-01 18:49:14 +01:00
void context_set_cursor_trap(bool value)
{
GetContext()->GetUiContext()->SetCursorTrap(value);
}
2018-02-01 18:49:14 +01:00
rct_window * context_open_window(rct_windowclass wc)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
return windowManager->OpenWindow(wc);
}
2018-02-01 18:49:14 +01:00
rct_window * context_open_window_view(rct_windowclass wc)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
return windowManager->OpenView(wc);
}
2017-09-05 20:55:18 +02:00
2018-02-01 18:49:14 +01:00
rct_window * context_open_detail_window(uint8 type, sint32 id)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
return windowManager->OpenDetails(type, id);
}
2017-09-06 15:09:18 +02:00
2018-02-01 18:49:14 +01:00
rct_window * context_open_intent(Intent * intent)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
return windowManager->OpenIntent(intent);
}
2017-09-10 11:02:16 +02:00
2018-02-01 18:49:14 +01:00
void context_broadcast_intent(Intent * intent)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->BroadcastIntent(*intent);
}
2017-10-06 23:03:48 +02:00
2018-02-01 18:49:14 +01:00
void context_force_close_window_by_class(rct_windowclass windowClass)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->ForceClose(windowClass);
}
2018-02-01 18:49:14 +01:00
rct_window * context_show_error(rct_string_id title, rct_string_id message)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
return windowManager->ShowError(title, message);
}
2018-02-01 18:49:14 +01:00
void context_update_map_tooltip()
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->UpdateMapTooltip();
}
2017-10-21 17:57:37 +02:00
2018-02-01 18:49:14 +01:00
void context_handle_input()
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->HandleInput();
}
2017-12-07 22:16:20 +01:00
2018-02-01 18:49:14 +01:00
void context_input_handle_keyboard(bool isTitle)
{
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->HandleKeyboard(isTitle);
}
2018-02-01 18:49:14 +01:00
bool context_read_bmp(void * * outPixels, uint32 * outWidth, uint32 * outHeight, const utf8 * path)
{
return GetContext()->GetUiContext()->ReadBMP(outPixels, outWidth, outHeight, std::string(path));
}
2018-02-01 18:49:14 +01:00
void context_quit()
{
GetContext()->Quit();
}
2017-07-28 19:43:48 +02:00
2018-02-01 18:49:14 +01:00
const utf8 * context_get_path_legacy(sint32 pathId)
{
static utf8 result[MAX_PATH];
auto path = GetContext()->GetPathLegacy(pathId);
String::Set(result, sizeof(result), path.c_str());
return result;
}
2018-02-01 18:49:14 +01:00
bool platform_open_common_file_dialog(utf8 * outFilename, file_dialog_desc * desc, size_t outSize)
{
try
{
2018-02-01 18:49:14 +01:00
FileDialogDesc desc2;
desc2.Type = (FILE_DIALOG_TYPE)desc->type;
desc2.Title = String::ToStd(desc->title);
desc2.InitialDirectory = String::ToStd(desc->initial_directory);
desc2.DefaultFilename = String::ToStd(desc->default_filename);
for (const auto &filter : desc->filters)
{
2018-02-01 18:49:14 +01:00
if (filter.name != nullptr)
{
2018-02-01 18:49:14 +01:00
desc2.Filters.push_back({ String::ToStd(filter.name), String::ToStd(filter.pattern) });
}
}
2018-02-01 18:49:14 +01:00
std::string result = GetContext()->GetUiContext()->ShowFileDialog(desc2);
String::Set(outFilename, outSize, result.c_str());
return !result.empty();
}
2018-02-01 18:49:14 +01:00
catch (const std::exception &ex)
{
2018-02-01 18:49:14 +01:00
log_error(ex.what());
outFilename[0] = '\0';
return false;
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
utf8 * platform_open_directory_browser(const utf8 * title)
{
try
{
2018-02-01 18:49:14 +01:00
std::string result = GetContext()->GetUiContext()->ShowDirectoryDialog(title);
return String::Duplicate(result.c_str());
}
2018-02-01 18:49:14 +01:00
catch (const std::exception &ex)
{
2018-02-01 18:49:14 +01:00
log_error(ex.what());
return nullptr;
}
2018-02-01 18:49:14 +01:00
}
bool platform_place_string_on_clipboard(utf8* target)
{
return GetContext()->GetUiContext()->SetClipboardText(target);
}
2017-12-02 00:48:46 +01:00
2018-02-01 18:49:14 +01:00
/**
* This function is deprecated.
* Use IPlatformEnvironment instead.
2018-02-01 18:49:14 +01:00
*/
void platform_get_user_directory(utf8 * outPath, const utf8 * subDirectory, size_t outSize)
{
auto env = GetContext()->GetPlatformEnvironment();
auto path = env->GetDirectoryPath(DIRBASE::USER);
if (!String::IsNullOrEmpty(subDirectory))
2017-12-02 00:48:46 +01:00
{
2018-02-01 18:49:14 +01:00
path = Path::Combine(path, subDirectory);
2017-12-02 00:48:46 +01:00
}
String::Set(outPath, outSize, path.c_str());
}
2018-02-01 18:49:14 +01:00
/**
* This function is deprecated.
* Use IPlatformEnvironment instead.
2018-02-01 18:49:14 +01:00
*/
void platform_get_openrct_data_path(utf8 * outPath, size_t outSize)
{
auto env = GetContext()->GetPlatformEnvironment();
auto path = env->GetDirectoryPath(DIRBASE::OPENRCT2);
String::Set(outPath, outSize, path.c_str());
}