From 94da3cf4224dc963f7fd7331dcb42aa3282270e5 Mon Sep 17 00:00:00 2001 From: Silent Date: Thu, 20 May 2021 17:06:53 +0200 Subject: [PATCH 01/16] Fix #13445: Make FileScanner::ScanDirectory return a unique_ptr Also fixes a resource leak in TitleSequence::GetSaves. --- contributors.md | 1 + src/openrct2-ui/interface/Theme.cpp | 2 +- src/openrct2-ui/windows/LoadSave.cpp | 2 +- src/openrct2/Context.cpp | 1 - src/openrct2/Game.cpp | 4 ++-- src/openrct2/core/FileIndex.hpp | 1 - src/openrct2/core/FileScanner.cpp | 11 +++++------ src/openrct2/core/FileScanner.h | 3 ++- src/openrct2/object/ImageTable.cpp | 2 +- src/openrct2/scripting/ScriptEngine.cpp | 2 +- src/openrct2/title/TitleSequence.cpp | 2 +- src/openrct2/title/TitleSequenceManager.cpp | 3 +-- test/tests/ReplayTests.cpp | 2 +- 13 files changed, 17 insertions(+), 19 deletions(-) diff --git a/contributors.md b/contributors.md index 0a04899ff0..0a8a3039d1 100644 --- a/contributors.md +++ b/contributors.md @@ -92,6 +92,7 @@ The following people are not part of the development team, but have been contrib * Helio Batimarqui (batimarqui) - Misc. * Keith Stellyes (keithstellyes) - Misc. * Bas Cantrijn (Basssiiie) - Misc. +* Adrian Zdanowicz (CookiePLMonster) - Misc. ## Bug fixes * (halfbro) diff --git a/src/openrct2-ui/interface/Theme.cpp b/src/openrct2-ui/interface/Theme.cpp index 5af3632d10..192d04d23a 100644 --- a/src/openrct2-ui/interface/Theme.cpp +++ b/src/openrct2-ui/interface/Theme.cpp @@ -536,7 +536,7 @@ namespace ThemeManager } auto themesPattern = Path::Combine(GetThemePath(), "*.json"); - auto scanner = std::unique_ptr(Path::ScanDirectory(themesPattern, true)); + auto scanner = Path::ScanDirectory(themesPattern, true); while (scanner->Next()) { auto fileInfo = scanner->GetFileInfo(); diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 574cd128c4..05c2ead6aa 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -913,7 +913,7 @@ static void window_loadsave_populate_list(rct_window* w, int32_t includeNewItem, safe_strcat_path(filter, "*", std::size(filter)); path_append_extension(filter, extToken, std::size(filter)); - auto scanner = std::unique_ptr(Path::ScanDirectory(filter, false)); + auto scanner = Path::ScanDirectory(filter, false); while (scanner->Next()) { LoadSaveListItem newListItem; diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 97caa7c4f9..fe376141b1 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1189,7 +1189,6 @@ namespace OpenRCT2 } } } - delete scanner; } #ifndef DISABLE_HTTP diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 5dcb15ccf7..50c8afb43f 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -678,7 +678,7 @@ static void limit_autosave_count(const size_t numberOfFilesToKeep, bool processL // At first, count how many autosaves there are { - auto scanner = std::unique_ptr(Path::ScanDirectory(filter, false)); + auto scanner = Path::ScanDirectory(filter, false); while (scanner->Next()) { autosavesCount++; @@ -693,7 +693,7 @@ static void limit_autosave_count(const size_t numberOfFilesToKeep, bool processL auto autosaveFiles = std::vector(autosavesCount); { - auto scanner = std::unique_ptr(Path::ScanDirectory(filter, false)); + auto scanner = Path::ScanDirectory(filter, false); for (size_t i = 0; i < autosavesCount; i++) { autosaveFiles[i].resize(MAX_PATH, 0); diff --git a/src/openrct2/core/FileIndex.hpp b/src/openrct2/core/FileIndex.hpp index 033a286b14..0e5d570a47 100644 --- a/src/openrct2/core/FileIndex.hpp +++ b/src/openrct2/core/FileIndex.hpp @@ -161,7 +161,6 @@ private: files.push_back(std::move(path)); } - delete scanner; } return ScanResult(stats, files); } diff --git a/src/openrct2/core/FileScanner.cpp b/src/openrct2/core/FileScanner.cpp index 56a435c986..9c79c500f7 100644 --- a/src/openrct2/core/FileScanner.cpp +++ b/src/openrct2/core/FileScanner.cpp @@ -342,18 +342,18 @@ private: #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -IFileScanner* Path::ScanDirectory(const std::string& pattern, bool recurse) +std::unique_ptr Path::ScanDirectory(const std::string& pattern, bool recurse) { #ifdef _WIN32 - return new FileScannerWindows(pattern, recurse); + return std::make_unique(pattern, recurse); #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - return new FileScannerUnix(pattern, recurse); + return std::make_unique(pattern, recurse); #endif } void Path::QueryDirectory(QueryDirectoryResult* result, const std::string& pattern) { - IFileScanner* scanner = Path::ScanDirectory(pattern, true); + auto scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) { const FileInfo* fileInfo = scanner->GetFileInfo(); @@ -366,12 +366,11 @@ void Path::QueryDirectory(QueryDirectoryResult* result, const std::string& patte result->FileDateModifiedChecksum = ror32(result->FileDateModifiedChecksum, 5); result->PathChecksum += GetPathChecksum(path); } - delete scanner; } std::vector Path::GetDirectories(const std::string& path) { - auto scanner = std::unique_ptr(ScanDirectory(path, false)); + auto scanner = ScanDirectory(path, false); auto baseScanner = static_cast(scanner.get()); std::vector children; diff --git a/src/openrct2/core/FileScanner.h b/src/openrct2/core/FileScanner.h index f3136e48f4..1e6c63d230 100644 --- a/src/openrct2/core/FileScanner.h +++ b/src/openrct2/core/FileScanner.h @@ -11,6 +11,7 @@ #include "../common.h" +#include #include #include @@ -50,7 +51,7 @@ namespace Path * @param recurse Whether to scan sub directories or not. * @returns A new FileScanner, this must be deleted when no longer needed. */ - IFileScanner* ScanDirectory(const std::string& pattern, bool recurse); + std::unique_ptr ScanDirectory(const std::string& pattern, bool recurse); /** * Scans a directory and all sub directories diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 0c70da90cc..15b04d1c70 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -274,7 +274,7 @@ std::string ImageTable::FindLegacyObject(const std::string& name) { // Search recursively for any file with the target name (case insensitive) auto filter = Path::Combine(objectsPath, "*.dat"); - auto scanner = std::unique_ptr(Path::ScanDirectory(filter, true)); + auto scanner = Path::ScanDirectory(filter, true); while (scanner->Next()) { auto currentName = Path::GetFileName(scanner->GetPathRelative()); diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index d1a1ff3217..db2f1a1801 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -443,7 +443,7 @@ void ScriptEngine::LoadPlugins() if (Path::DirectoryExists(base)) { auto pattern = Path::Combine(base, "*.js"); - auto scanner = std::unique_ptr(Path::ScanDirectory(pattern, true)); + auto scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) { auto path = std::string(scanner->GetPath()); diff --git a/src/openrct2/title/TitleSequence.cpp b/src/openrct2/title/TitleSequence.cpp index 87d513ae4f..c5e47ca72a 100644 --- a/src/openrct2/title/TitleSequence.cpp +++ b/src/openrct2/title/TitleSequence.cpp @@ -292,7 +292,7 @@ static std::vector GetSaves(const std::string& directory) std::vector saves; auto pattern = Path::Combine(directory, "*.sc6;*.sv6"); - IFileScanner* scanner = Path::ScanDirectory(pattern, true); + auto scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) { const utf8* path = scanner->GetPathRelative(); diff --git a/src/openrct2/title/TitleSequenceManager.cpp b/src/openrct2/title/TitleSequenceManager.cpp index 02c8c381f0..553c061596 100644 --- a/src/openrct2/title/TitleSequenceManager.cpp +++ b/src/openrct2/title/TitleSequenceManager.cpp @@ -209,12 +209,11 @@ namespace TitleSequenceManager static void Scan(const std::string& directory) { auto pattern = Path::Combine(directory, "script.txt;*.parkseq"); - IFileScanner* fileScanner = Path::ScanDirectory(pattern, true); + auto fileScanner = Path::ScanDirectory(pattern, true); while (fileScanner->Next()) { AddSequence(fileScanner->GetPath()); } - delete fileScanner; } static void AddSequence(const std::string& scanPath) diff --git a/test/tests/ReplayTests.cpp b/test/tests/ReplayTests.cpp index 7377a57110..83b8c8f4b5 100644 --- a/test/tests/ReplayTests.cpp +++ b/test/tests/ReplayTests.cpp @@ -53,7 +53,7 @@ static std::vector GetReplayFiles() std::string replayPathPattern = Path::Combine(replayPath, "*.sv6r"); std::vector files; - std::unique_ptr scanner = std::unique_ptr(Path::ScanDirectory(replayPathPattern, true)); + auto scanner = Path::ScanDirectory(replayPathPattern, true); while (scanner->Next()) { ReplayTestData test; From 95388cfbb1f1f06cb9eee719e8633544b8e8d509 Mon Sep 17 00:00:00 2001 From: Silent Date: Fri, 21 May 2021 16:55:07 +0200 Subject: [PATCH 02/16] Add File::GetSize to get object size in a simpler way Drastically reduces startup speed because of the optimization applied to ObjectAsset::GetSize - now the file size is obtained without reading the entire file into memory. --- distribution/changelog.txt | 1 + src/openrct2/core/File.cpp | 7 ++++++- src/openrct2/core/File.h | 3 ++- src/openrct2/object/Object.cpp | 13 +++---------- src/openrct2/object/Object.h | 4 ++-- src/openrct2/platform/Platform.Posix.cpp | 15 ++++++++++++++- src/openrct2/platform/Platform.Win32.cpp | 17 ++++++++++++++++- src/openrct2/platform/Platform2.h | 3 ++- 8 files changed, 46 insertions(+), 17 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index f0c2a3da24..eda7cd7591 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -20,6 +20,7 @@ - Fix: [#14587] Confusing message when joining server with mismatched network version. - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. +- Improved: [#14712]: Improve startup times. 0.3.3 (2021-03-13) ------------------------------------------------------------------------ diff --git a/src/openrct2/core/File.cpp b/src/openrct2/core/File.cpp index df722e1196..99bc40b93d 100644 --- a/src/openrct2/core/File.cpp +++ b/src/openrct2/core/File.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -123,6 +123,11 @@ namespace File { return Platform::GetLastModified(path); } + + uint64_t GetSize(std::string_view path) + { + return Platform::GetFileSize(path); + } } // namespace File bool writeentirefile(const utf8* path, const void* buffer, size_t length) diff --git a/src/openrct2/core/File.h b/src/openrct2/core/File.h index 9dc216042e..cdd6179fa7 100644 --- a/src/openrct2/core/File.h +++ b/src/openrct2/core/File.h @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -26,4 +26,5 @@ namespace File std::vector ReadAllLines(std::string_view path); void WriteAllBytes(const std::string& path, const void* buffer, size_t length); uint64_t GetLastModified(const std::string& path); + uint64_t GetSize(std::string_view path); } // namespace File diff --git a/src/openrct2/object/Object.cpp b/src/openrct2/object/Object.cpp index 0d221293e5..6de569acdf 100644 --- a/src/openrct2/object/Object.cpp +++ b/src/openrct2/object/Object.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -252,18 +252,11 @@ bool ObjectAsset::IsAvailable() const } } -size_t ObjectAsset::GetSize() const +uint64_t ObjectAsset::GetSize() const { if (_zipPath.empty()) { - try - { - return File::ReadAllBytes(_path).size(); - } - catch (...) - { - return 0; - } + return File::GetSize(_path); } else { diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 47e9ee87d5..7e3a496e86 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -223,7 +223,7 @@ public: } bool IsAvailable() const; - size_t GetSize() const; + uint64_t GetSize() const; std::unique_ptr GetStream() const; }; diff --git a/src/openrct2/platform/Platform.Posix.cpp b/src/openrct2/platform/Platform.Posix.cpp index 8889749720..dc1184564d 100644 --- a/src/openrct2/platform/Platform.Posix.cpp +++ b/src/openrct2/platform/Platform.Posix.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -177,6 +177,19 @@ namespace Platform return lastModified; } + uint64_t GetFileSize(std::string_view path) + { + uint64_t size = 0; + struct stat statInfo + { + }; + if (stat(std::string(path).c_str(), &statInfo) == 0) + { + size = statInfo.st_size; + } + return size; + } + bool ShouldIgnoreCase() { return false; diff --git a/src/openrct2/platform/Platform.Win32.cpp b/src/openrct2/platform/Platform.Win32.cpp index d7d22fbbea..4a7f203e96 100644 --- a/src/openrct2/platform/Platform.Win32.cpp +++ b/src/openrct2/platform/Platform.Win32.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -554,6 +554,21 @@ namespace Platform return lastModified; } + uint64_t GetFileSize(std::string_view path) + { + uint64_t size = 0; + auto pathW = String::ToWideChar(path); + WIN32_FILE_ATTRIBUTE_DATA attributes; + if (GetFileAttributesExW(pathW.c_str(), GetFileExInfoStandard, &attributes) != FALSE) + { + ULARGE_INTEGER fileSize; + fileSize.LowPart = attributes.nFileSizeLow; + fileSize.HighPart = attributes.nFileSizeHigh; + size = fileSize.QuadPart; + } + return size; + } + bool ShouldIgnoreCase() { return true; diff --git a/src/openrct2/platform/Platform2.h b/src/openrct2/platform/Platform2.h index 6189f21b96..98d886d282 100644 --- a/src/openrct2/platform/Platform2.h +++ b/src/openrct2/platform/Platform2.h @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -39,6 +39,7 @@ namespace Platform bool IsPathSeparator(char c); utf8* GetAbsolutePath(utf8* buffer, size_t bufferSize, const utf8* relativePath); uint64_t GetLastModified(const std::string& path); + uint64_t GetFileSize(std::string_view path); std::string ResolveCasing(const std::string& path, bool fileExists); rct2_time GetTimeLocal(); rct2_date GetDateLocal(); From 724a3c0579ff09ac19de3744d60c937e46a172a5 Mon Sep 17 00:00:00 2001 From: Silent Date: Fri, 21 May 2021 17:51:26 +0200 Subject: [PATCH 03/16] Obtain file sizes without seeking where possible --- src/openrct2/core/File.cpp | 4 +--- src/openrct2/core/FileStream.cpp | 13 +++++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/openrct2/core/File.cpp b/src/openrct2/core/File.cpp index 99bc40b93d..4e7eba3fea 100644 --- a/src/openrct2/core/File.cpp +++ b/src/openrct2/core/File.cpp @@ -57,8 +57,7 @@ namespace File } std::vector result; - fs.seekg(0, std::ios::end); - auto fsize = static_cast(fs.tellg()); + auto fsize = Platform::GetFileSize(path); if (fsize > SIZE_MAX) { std::string message = String::StdFormat( @@ -68,7 +67,6 @@ namespace File else { result.resize(fsize); - fs.seekg(0); fs.read(reinterpret_cast(result.data()), result.size()); fs.exceptions(fs.failbit); } diff --git a/src/openrct2/core/FileStream.cpp b/src/openrct2/core/FileStream.cpp index 3a1ff1654b..3eb85d8987 100644 --- a/src/openrct2/core/FileStream.cpp +++ b/src/openrct2/core/FileStream.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -16,6 +16,8 @@ #ifndef _WIN32 # include +#else +# include #endif #if defined(__linux__) && !defined(__ANDROID__) @@ -98,9 +100,12 @@ namespace OpenRCT2 throw IOException(String::StdFormat("Unable to open '%s'", path)); } - Seek(0, STREAM_SEEK_END); - _fileSize = GetPosition(); - Seek(0, STREAM_SEEK_BEGIN); +#ifdef _WIN32 + _fileSize = _filelengthi64(_fileno(_file)); +#else + std::error_code ec; + _fileSize = fs::file_size(fs::u8path(path), ec); +#endif _ownsFilePtr = true; } From e280eb2083dc96e936706a27f69460b72b28ed85 Mon Sep 17 00:00:00 2001 From: Silent Date: Fri, 21 May 2021 18:51:00 +0200 Subject: [PATCH 04/16] FileStream::Read: Throw the exception basing on fread return value This change removes ftell/GetPosition() from hot spots during the startup, "optimizing" the function for success cases - reading past EOF should never/rarely happen so it seems fine to let it try to read before checking --- src/openrct2/core/FileStream.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/openrct2/core/FileStream.cpp b/src/openrct2/core/FileStream.cpp index 3eb85d8987..68c0b52692 100644 --- a/src/openrct2/core/FileStream.cpp +++ b/src/openrct2/core/FileStream.cpp @@ -165,13 +165,9 @@ namespace OpenRCT2 void FileStream::Read(void* buffer, uint64_t length) { - uint64_t remainingBytes = GetLength() - GetPosition(); - if (length <= remainingBytes) + if (fread(buffer, 1, static_cast(length), _file) == length) { - if (fread(buffer, static_cast(length), 1, _file) == 1) - { - return; - } + return; } throw IOException("Attempted to read past end of file."); } From 38c7a70025e7cd2054ea04c66a4bd68ffb7de4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= Date: Sun, 23 May 2021 15:45:48 +0300 Subject: [PATCH 05/16] Fix #14710: Preview not shown without enough money (#14711) * Fix #14710: Preview not shown without enough money * Bump up network version * Add changelog.txt entry --- distribution/changelog.txt | 1 + src/openrct2/actions/GameAction.cpp | 3 ++- src/openrct2/network/NetworkBase.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index eda7cd7591..88d71712d7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -20,6 +20,7 @@ - Fix: [#14587] Confusing message when joining server with mismatched network version. - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. +- Fix: [#14710] Ride/Track Design preview does not show if it costs more money than available. - Improved: [#14712]: Improve startup times. 0.3.3 (2021-03-13) diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index adc8606a62..f957c87d0a 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -310,7 +310,8 @@ namespace GameActions if (result->Error == GameActions::Status::Ok) { - if (!finance_check_affordability(result->Cost, action->GetFlags())) + if ((action->GetFlags() & GAME_COMMAND_FLAG_APPLY) + && !finance_check_affordability(result->Cost, action->GetFlags())) { result->Error = GameActions::Status::InsufficientFunds; result->ErrorTitle = STR_CANT_DO_THIS; diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index a80167a71f..dac50877fb 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -36,7 +36,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "14" +#define NETWORK_STREAM_VERSION "15" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; From fb602ec0c938db5075a56e48fee9c9c7efb9ab6f Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 May 2021 15:23:52 +0200 Subject: [PATCH 06/16] Fix allocator mismatch in SawyerChunk on Windows with Debug This change allows to use HeapReAlloc in FinaliseLargeTempBuffer when running Debug builds. --- src/openrct2/rct12/SawyerChunk.cpp | 5 +++-- src/openrct2/rct12/SawyerChunkReader.cpp | 11 +++++++---- src/openrct2/rct12/SawyerChunkReader.h | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/openrct2/rct12/SawyerChunk.cpp b/src/openrct2/rct12/SawyerChunk.cpp index b5db22a579..6873c94924 100644 --- a/src/openrct2/rct12/SawyerChunk.cpp +++ b/src/openrct2/rct12/SawyerChunk.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -10,6 +10,7 @@ #include "SawyerChunk.h" #include "../core/Memory.hpp" +#include "SawyerChunkReader.h" SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, void* data, size_t length) { @@ -20,5 +21,5 @@ SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, void* data, size_t length) SawyerChunk::~SawyerChunk() { - Memory::Free(_data); + SawyerChunkReader::FreeChunk(_data); } diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index f1bf44933f..4f584130ae 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -158,6 +158,11 @@ void SawyerChunkReader::ReadChunk(void* dst, size_t length) } } +void SawyerChunkReader::FreeChunk(void* data) +{ + FreeLargeTempBuffer(data); +} + size_t SawyerChunkReader::DecodeChunk(void* dst, size_t dstCapacity, const void* src, const sawyercoding_chunk_header& header) { size_t resultLength; @@ -315,9 +320,7 @@ void* SawyerChunkReader::AllocateLargeTempBuffer() void* SawyerChunkReader::FinaliseLargeTempBuffer(void* buffer, size_t len) { #ifdef __USE_HEAP_ALLOC__ - auto finalBuffer = std::malloc(len); - std::memcpy(finalBuffer, buffer, len); - HeapFree(GetProcessHeap(), 0, buffer); + auto finalBuffer = HeapReAlloc(GetProcessHeap(), 0, buffer, len); #else auto finalBuffer = static_cast(std::realloc(buffer, len)); #endif diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 8fb370b25e..9d68f55726 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -84,6 +84,11 @@ public: return result; } + /** + * Frees the chunk data, to be used when destructing SawyerChunks + */ + static void FreeChunk(void* data); + private: static size_t DecodeChunk(void* dst, size_t dstCapacity, const void* src, const sawyercoding_chunk_header& header); static size_t DecodeChunkRLERepeat(void* dst, size_t dstCapacity, const void* src, size_t srcLength); From 66abc696908cd3bfb8f51a40e65d5b07bef6fec7 Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 May 2021 15:26:59 +0200 Subject: [PATCH 07/16] Add a persistentChunks flag to SawyerChunkReader New behaviour of SawyerChunkReader is to skip shrinking the chunk memory unless persistentChunks is set to true. At the moment all uses of SawyerChunks created by the reader are temporary and shrinking memory right before freeing them is a waste of time. Speeds up loading times and index building --- distribution/changelog.txt | 2 +- src/openrct2/rct12/SawyerChunkReader.cpp | 13 ++++++++++--- src/openrct2/rct12/SawyerChunkReader.h | 6 ++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 88d71712d7..5f70d38fb5 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -21,7 +21,7 @@ - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. - Fix: [#14710] Ride/Track Design preview does not show if it costs more money than available. -- Improved: [#14712]: Improve startup times. +- Improved: [#14712, #14716]: Improve startup times. 0.3.3 (2021-03-13) ------------------------------------------------------------------------ diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index 4f584130ae..cf03dfdc5b 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -27,8 +27,9 @@ constexpr const char* EXCEPTION_MSG_DESTINATION_TOO_SMALL = "Chunk data larger t constexpr const char* EXCEPTION_MSG_INVALID_CHUNK_ENCODING = "Invalid chunk encoding."; constexpr const char* EXCEPTION_MSG_ZERO_SIZED_CHUNK = "Encountered zero-sized chunk."; -SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream) +SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream, bool persistentChunks) : _stream(stream) + , _createsPersistentChunks(persistentChunks) { } @@ -78,7 +79,10 @@ std::shared_ptr SawyerChunkReader::ReadChunk() { throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); } - buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + if (_createsPersistentChunks) + { + buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + } return std::make_shared( static_cast(header.encoding), buffer, uncompressedLength); } @@ -126,7 +130,10 @@ std::shared_ptr SawyerChunkReader::ReadChunkTrack() { throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); } - buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + if (_createsPersistentChunks) + { + buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + } return std::make_shared(SAWYER_ENCODING::RLE, buffer, uncompressedLength); } catch (const std::exception&) diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 9d68f55726..0873c8b845 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -36,15 +36,17 @@ namespace OpenRCT2 /** * Reads sawyer encoding chunks from a data stream. This can be used to read - * SC6, SV6 and RCT2 objects. + * SC6, SV6 and RCT2 objects. persistentChunks is a hint to the reader that the chunk will be preserved, + * and thus the chunk memory should be shrunk. */ class SawyerChunkReader final { private: OpenRCT2::IStream* const _stream = nullptr; + const bool _createsPersistentChunks = false; public: - explicit SawyerChunkReader(OpenRCT2::IStream* stream); + explicit SawyerChunkReader(OpenRCT2::IStream* stream, bool persistentChunks = false); /** * Skips the next chunk in the stream without decoding or reading its data From dbd84f9f4017438155bad980e8182d8df69d56f4 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 23 May 2021 07:41:34 -0600 Subject: [PATCH 08/16] Fix #14415: Entrances/exits are removed when built on top of each other (#14490) --- distribution/changelog.txt | 1 + src/openrct2/ride/Ride.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 88d71712d7..7c55519952 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -14,6 +14,7 @@ - Fix: [#13986] OpenGL: Track preview window, flip/rotate button do not update the thumbnail. - Fix: [#14315] Crash when trying to rename Air Powered Vertical Coaster in Korean. - Fix: [#14330] join_server uses default_port from config. +- Fix: [#14415] Entrances/exits are removed when built on top of each other. - Fix: [#14449] Surface smoothing at extra zoom levels not working. - Fix: [#14468] Cannot close Options window on Android. - Fix: [#14493] [Plugin] isHidden only works for tile elements up to the first element with a base height of over 32. diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 60c3d42e7d..4f8fb4e147 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -6671,6 +6671,8 @@ void sub_6CB945(Ride* ride) { if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) continue; + if (tileElement->base_height != locationCoords.z) + continue; if (tileElement->AsEntrance()->GetRideIndex() != ride->id) continue; if (tileElement->AsEntrance()->GetEntranceType() > ENTRANCE_TYPE_RIDE_EXIT) From 9a76224a22b4b041ff31a0c4928426ac5bdd57c8 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sun, 23 May 2021 15:43:57 +0200 Subject: [PATCH 09/16] =?UTF-8?q?Downgrade=20=E2=80=9CImage=20table=20long?= =?UTF-8?q?er=20than=20expected=E2=80=9D=20to=20a=20verbose=20warning=20(#?= =?UTF-8?q?14722)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are lots of custom objects like this and there is little point spewing the console full of them, since they’re unlikely to cause many problems. --- src/openrct2/object/ImageTable.cpp | 2 +- src/openrct2/object/Object.h | 1 + src/openrct2/object/ObjectFactory.cpp | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 15b04d1c70..ab2e033ba3 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -315,7 +315,7 @@ void ImageTable::Read(IReadObjectContext* context, OpenRCT2::IStream* stream) uint64_t remainingBytes = stream->GetLength() - stream->GetPosition() - headerTableSize; if (remainingBytes > imageDataSize) { - context->LogWarning(ObjectError::BadImageTable, "Image table size longer than expected."); + context->LogVerbose(ObjectError::BadImageTable, "Image table size longer than expected."); imageDataSize = static_cast(remainingBytes); } diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 7e3a496e86..0f3761986c 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -237,6 +237,7 @@ struct IReadObjectContext virtual std::vector GetData(std::string_view path) abstract; virtual ObjectAsset GetAsset(std::string_view path) abstract; + virtual void LogVerbose(ObjectError code, const utf8* text) abstract; virtual void LogWarning(ObjectError code, const utf8* text) abstract; virtual void LogError(ObjectError code, const utf8* text) abstract; }; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 98a045d31c..db5865e54a 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -105,10 +105,15 @@ private: std::string _identifier; bool _loadImages; std::string _basePath; + bool _wasVerbose = false; bool _wasWarning = false; bool _wasError = false; public: + bool WasVerbose() const + { + return _wasVerbose; + } bool WasWarning() const { return _wasWarning; @@ -161,6 +166,16 @@ public: return {}; } + void LogVerbose(ObjectError code, const utf8* text) override + { + _wasVerbose = true; + + if (!String::IsNullOrEmpty(text)) + { + log_verbose("[%s] Info (%d): %s", _identifier.c_str(), code, text); + } + } + void LogWarning(ObjectError code, const utf8* text) override { _wasWarning = true; From 2b4b204ad8f8ec911cd079e86b1177f7a4994d35 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 23 May 2021 19:58:47 +0300 Subject: [PATCH 10/16] Fix #14724: Money was ignored for ride creation --- src/openrct2/actions/GameAction.cpp | 3 +-- src/openrct2/management/Finance.cpp | 2 +- src/openrct2/ride/TrackDesign.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index f957c87d0a..adc8606a62 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -310,8 +310,7 @@ namespace GameActions if (result->Error == GameActions::Status::Ok) { - if ((action->GetFlags() & GAME_COMMAND_FLAG_APPLY) - && !finance_check_affordability(result->Cost, action->GetFlags())) + if (!finance_check_affordability(result->Cost, action->GetFlags())) { result->Error = GameActions::Status::InsufficientFunds; result->ErrorTitle = STR_CANT_DO_THIS; diff --git a/src/openrct2/management/Finance.cpp b/src/openrct2/management/Finance.cpp index 3de1af67f5..2081230b2d 100644 --- a/src/openrct2/management/Finance.cpp +++ b/src/openrct2/management/Finance.cpp @@ -75,7 +75,7 @@ bool finance_check_money_required(uint32_t flags) */ bool finance_check_affordability(money32 cost, uint32_t flags) { - return cost <= 0 || !finance_check_money_required(flags) || cost <= gCash; + return !finance_check_money_required(flags) || cost <= 0 || cost <= gCash; } /** diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 44292c0e0f..b47bcd08e8 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -1586,7 +1586,7 @@ static bool track_design_place_ride(TrackDesign* td6, const CoordsXYZ& origin, R } else if (_trackDesignPlaceOperation == PTD_OPERATION_PLACE_QUERY) { - flags = 0; + flags = GAME_COMMAND_FLAG_NO_SPEND; } if (_trackDesignPlaceIsReplay) { From 7c8beededb1a6653854786d50b1f72e3bb152a1f Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 23 May 2021 20:01:42 +0300 Subject: [PATCH 11/16] Bump network version --- src/openrct2/network/NetworkBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index dac50877fb..76fa8088b9 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -36,7 +36,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "15" +#define NETWORK_STREAM_VERSION "16" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; From ebcdfd06e902b5424303e0a6ddd7b5de600a38ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= Date: Mon, 24 May 2021 01:11:04 +0300 Subject: [PATCH 12/16] Fix #14707: Crash when window is closed during text input --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/TextInput.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7c55519952..d610aba196 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -21,6 +21,7 @@ - Fix: [#14587] Confusing message when joining server with mismatched network version. - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. +- Fix: [#14707] Crash when window is closed during text input. - Fix: [#14710] Ride/Track Design preview does not show if it costs more money than available. - Improved: [#14712]: Improve startup times. diff --git a/src/openrct2-ui/windows/TextInput.cpp b/src/openrct2-ui/windows/TextInput.cpp index 956252064c..dd5fd1336b 100644 --- a/src/openrct2-ui/windows/TextInput.cpp +++ b/src/openrct2-ui/windows/TextInput.cpp @@ -408,6 +408,9 @@ void window_text_input_open( void window_text_input_key(rct_window* w, char keychar) { + const auto wndNumber = w->number; + const auto wndClass = w->classification; + // If the return button is pressed stop text input if (keychar == '\r') { @@ -417,5 +420,9 @@ void window_text_input_key(rct_window* w, char keychar) textInputWindow->OnReturnPressed(); } } - w->Invalidate(); + + // The window can be potentially closed within a callback, we need to check if its still alive. + w = window_find_by_number(wndClass, wndNumber); + if (w != nullptr) + w->Invalidate(); } From 999157381779aa1bd631e6214998024064abe2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= Date: Mon, 24 May 2021 13:38:31 +0300 Subject: [PATCH 13/16] Fix #14682: Crash when painting Swinging Ships with invalid subtype --- distribution/changelog.txt | 1 + src/openrct2/ride/thrill/SwingingShip.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index d610aba196..77c0b6aeec 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -21,6 +21,7 @@ - Fix: [#14587] Confusing message when joining server with mismatched network version. - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. +- Fix: [#14682] Crash when painting Swinging Ships with invalid subtype. - Fix: [#14707] Crash when window is closed during text input. - Fix: [#14710] Ride/Track Design preview does not show if it costs more money than available. - Improved: [#14712]: Improve startup times. diff --git a/src/openrct2/ride/thrill/SwingingShip.cpp b/src/openrct2/ride/thrill/SwingingShip.cpp index 35c4216739..9726fca15e 100644 --- a/src/openrct2/ride/thrill/SwingingShip.cpp +++ b/src/openrct2/ride/thrill/SwingingShip.cpp @@ -63,6 +63,11 @@ static void paint_swinging_ship_structure( const TileElement* savedTileElement = static_cast(session->CurrentlyDrawnItem); rct_ride_entry* rideEntry = get_ride_entry(ride->subtype); + if (rideEntry == nullptr) + { + return; + } + Vehicle* vehicle = nullptr; int8_t xOffset = !(direction & 1) ? axisOffset : 0; From 89eae5198b31dcabccd349434e88fdf78ac7dc25 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 24 May 2021 16:30:46 +0200 Subject: [PATCH 14/16] Add option to make water opaque --- data/language/en-GB.txt | 1 + distribution/changelog.txt | 1 + src/openrct2-ui/windows/TopToolbar.cpp | 70 ++++++++++++------- src/openrct2/config/Config.cpp | 2 + src/openrct2/config/Config.h | 1 + src/openrct2/interface/Viewport.h | 1 + src/openrct2/localisation/StringIds.h | 2 + .../paint/tile_element/Paint.Surface.cpp | 4 +- .../paint/tile_element/Paint.Surface.h | 3 + 9 files changed, 57 insertions(+), 28 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 0e7811f5df..39507e0a40 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3682,6 +3682,7 @@ STR_6436 :Toggle invisibility STR_6437 :Invisible STR_6438 :I STR_6439 :Tile Inspector: Toggle invisibility +STR_6440 :Opaque water ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7464bb2c8c..f7cd4c99cf 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,6 +6,7 @@ - Feature: [#14538] [Plugin] Add property for getting current plugin api version. - Feature: [#14620] [Plugin] Add properties related to guest generation. - Feature: [#14636] [Plugin] Add properties related to climate and weather. +- Feature: [#14731] Opaque water (like in RCT1). - Change: [#14496] [Plugin] Rename Object to LoadedObject to fix conflicts with Typescript's Object interface. - Change: [#14536] [Plugin] Rename ListView to ListViewWidget to make it consistent with names of other widgets. - Fix: [#11829] Visual glitches and crashes when using RCT1 assets from mismatched or corrupt CSG1.DAT and CSG1i.DAT files. diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 3b7a1545da..ff57dc0db5 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -127,19 +127,22 @@ enum FILE_MENU_DDIDX { enum TOP_TOOLBAR_VIEW_MENU_DDIDX { DDIDX_UNDERGROUND_INSIDE = 0, - DDIDX_HIDE_BASE = 1, - DDIDX_HIDE_VERTICAL = 2, - DDIDX_SEETHROUGH_RIDES = 4, - DDIDX_SEETHROUGH_SCENARY = 5, - DDIDX_SEETHROUGH_PATHS = 6, - DDIDX_INVISIBLE_SUPPORTS = 7, - DDIDX_INVISIBLE_PEEPS = 8, - DDIDX_LAND_HEIGHTS = 10, - DDIDX_TRACK_HEIGHTS = 11, - DDIDX_PATH_HEIGHTS = 12, - // 13 is a separator - DDIDX_VIEW_CLIPPING = 14, - DDIDX_HIGHLIGHT_PATH_ISSUES = 15, + DDIDX_OPAQUE_WATER = 1, + DDIDX_HIDE_BASE = 2, + DDIDX_HIDE_VERTICAL = 3, + // separator + DDIDX_SEETHROUGH_RIDES = 5, + DDIDX_SEETHROUGH_SCENERY = 6, + DDIDX_SEETHROUGH_PATHS = 7, + DDIDX_INVISIBLE_SUPPORTS = 8, + DDIDX_INVISIBLE_PEEPS = 9, + // separator + DDIDX_LAND_HEIGHTS = 11, + DDIDX_TRACK_HEIGHTS = 12, + DDIDX_PATH_HEIGHTS = 13, + // separator + DDIDX_VIEW_CLIPPING = 15, + DDIDX_HIGHLIGHT_PATH_ISSUES = 16, TOP_TOOLBAR_VIEW_MENU_COUNT }; @@ -3607,14 +3610,14 @@ static void top_toolbar_network_menu_dropdown(int16_t dropdownIndex) static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) { using namespace Dropdown; - constexpr Item items[] = { ToggleOption(DDIDX_UNDERGROUND_INSIDE, STR_UNDERGROUND_VIEW), + ToggleOption(DDIDX_OPAQUE_WATER, STR_VIEWPORT_OPAQUE_WATER), ToggleOption(DDIDX_HIDE_BASE, STR_REMOVE_BASE_LAND), ToggleOption(DDIDX_HIDE_VERTICAL, STR_REMOVE_VERTICAL_FACES), Separator(), ToggleOption(DDIDX_SEETHROUGH_RIDES, STR_SEE_THROUGH_RIDES), - ToggleOption(DDIDX_SEETHROUGH_SCENARY, STR_SEE_THROUGH_SCENERY), + ToggleOption(DDIDX_SEETHROUGH_SCENERY, STR_SEE_THROUGH_SCENERY), ToggleOption(DDIDX_SEETHROUGH_PATHS, STR_SEE_THROUGH_PATHS), ToggleOption(DDIDX_INVISIBLE_SUPPORTS, STR_INVISIBLE_SUPPORTS), ToggleOption(DDIDX_INVISIBLE_PEEPS, STR_INVISIBLE_PEOPLE), @@ -3626,6 +3629,7 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) ToggleOption(DDIDX_VIEW_CLIPPING, STR_VIEW_CLIPPING_MENU), ToggleOption(DDIDX_HIGHLIGHT_PATH_ISSUES, STR_HIGHLIGHT_PATH_ISSUES_MENU), }; + static_assert(ItemIDsMatchIndices(items)); SetItems(items); @@ -3637,33 +3641,41 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) // Set checkmarks rct_viewport* mainViewport = window_get_main()->viewport; if (mainViewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE) - Dropdown::SetChecked(0, true); + Dropdown::SetChecked(DDIDX_UNDERGROUND_INSIDE, true); + if (gConfigGeneral.opaque_water) + Dropdown::SetChecked(DDIDX_OPAQUE_WATER, true); if (mainViewport->flags & VIEWPORT_FLAG_HIDE_BASE) - Dropdown::SetChecked(1, true); + Dropdown::SetChecked(DDIDX_HIDE_BASE, true); if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VERTICAL) - Dropdown::SetChecked(2, true); + Dropdown::SetChecked(DDIDX_HIDE_VERTICAL, true); if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_RIDES) - Dropdown::SetChecked(4, true); + Dropdown::SetChecked(DDIDX_SEETHROUGH_RIDES, true); if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_SCENERY) - Dropdown::SetChecked(5, true); + Dropdown::SetChecked(DDIDX_SEETHROUGH_SCENERY, true); if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_PATHS) - Dropdown::SetChecked(6, true); + Dropdown::SetChecked(DDIDX_SEETHROUGH_PATHS, true); if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_SUPPORTS) - Dropdown::SetChecked(7, true); + Dropdown::SetChecked(DDIDX_INVISIBLE_SUPPORTS, true); if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_PEEPS) - Dropdown::SetChecked(8, true); + Dropdown::SetChecked(DDIDX_INVISIBLE_PEEPS, true); if (mainViewport->flags & VIEWPORT_FLAG_LAND_HEIGHTS) - Dropdown::SetChecked(10, true); + Dropdown::SetChecked(DDIDX_LAND_HEIGHTS, true); if (mainViewport->flags & VIEWPORT_FLAG_TRACK_HEIGHTS) - Dropdown::SetChecked(11, true); + Dropdown::SetChecked(DDIDX_TRACK_HEIGHTS, true); if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS) - Dropdown::SetChecked(12, true); + Dropdown::SetChecked(DDIDX_PATH_HEIGHTS, true); if (mainViewport->flags & VIEWPORT_FLAG_CLIP_VIEW) Dropdown::SetChecked(DDIDX_VIEW_CLIPPING, true); if (mainViewport->flags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) Dropdown::SetChecked(DDIDX_HIGHLIGHT_PATH_ISSUES, true); gDropdownDefaultIndex = DDIDX_UNDERGROUND_INSIDE; + + // Opaque water relies on RCT1 sprites. + if (!is_csg_loaded()) + { + Dropdown::SetDisabled(DDIDX_OPAQUE_WATER, true); + } } /** @@ -3680,6 +3692,10 @@ static void top_toolbar_view_menu_dropdown(int16_t dropdownIndex) case DDIDX_UNDERGROUND_INSIDE: w->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE; break; + case DDIDX_OPAQUE_WATER: + gConfigGeneral.opaque_water ^= 1; + config_save_default(); + break; case DDIDX_HIDE_BASE: w->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE; break; @@ -3689,7 +3705,7 @@ static void top_toolbar_view_menu_dropdown(int16_t dropdownIndex) case DDIDX_SEETHROUGH_RIDES: w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_RIDES; break; - case DDIDX_SEETHROUGH_SCENARY: + case DDIDX_SEETHROUGH_SCENERY: w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_SCENERY; break; case DDIDX_SEETHROUGH_PATHS: diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index a1873c0ccf..1a1ff0b5b7 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -227,6 +227,7 @@ namespace Config model->show_real_names_of_guests = reader->GetBoolean("show_real_names_of_guests", true); model->allow_early_completion = reader->GetBoolean("allow_early_completion", false); model->transparent_screenshot = reader->GetBoolean("transparent_screenshot", true); + model->opaque_water = reader->GetBoolean("opaque_water", false); model->last_version_check_time = reader->GetInt64("last_version_check_time", 0); } } @@ -304,6 +305,7 @@ namespace Config writer->WriteBoolean("allow_early_completion", model->allow_early_completion); writer->WriteEnum("virtual_floor_style", model->virtual_floor_style, Enum_VirtualFloorStyle); writer->WriteBoolean("transparent_screenshot", model->transparent_screenshot); + writer->WriteBoolean("opaque_water", model->opaque_water); writer->WriteInt64("last_version_check_time", model->last_version_check_time); } diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index badf2b1fdf..3f516dd0d2 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -58,6 +58,7 @@ struct GeneralConfiguration bool disable_lightning_effect; bool show_guest_purchases; bool transparent_screenshot; + bool opaque_water; // Localisation int32_t language; diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index cc4750ab6a..8393b1628d 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -49,6 +49,7 @@ enum VIEWPORT_FLAG_CLIP_VIEW = (1 << 17), VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES = (1 << 18), VIEWPORT_FLAG_TRANSPARENT_BACKGROUND = (1 << 19), + VIEWPORT_FLAG_OPAQUE_WATER = (1 << 20), }; enum class ViewportInteractionItem : uint8_t diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 70e41b5e5a..3118b5a81e 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3941,6 +3941,8 @@ enum STR_TILE_INSPECTOR_INVISIBLE_SHORT = 6438, STR_SHORTCUT_TOGGLE_INVISIBILITY = 6439, + STR_VIEWPORT_OPAQUE_WATER = 6440, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings }; diff --git a/src/openrct2/paint/tile_element/Paint.Surface.cpp b/src/openrct2/paint/tile_element/Paint.Surface.cpp index 22a4202c9c..3285a519db 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.cpp +++ b/src/openrct2/paint/tile_element/Paint.Surface.cpp @@ -1315,7 +1315,9 @@ void surface_paint(paint_session* session, uint8_t direction, uint16_t height, c | EnumValue(FilterPaletteID::PaletteWater) << 19; PaintAddImageAsParent(session, image_id, 0, 0, 32, 32, -1, waterHeight); - PaintAttachToPreviousPS(session, SPR_WATER_OVERLAY + image_offset, 0, 0); + const bool opaque = (gConfigGeneral.opaque_water) && !(session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE); + const uint32_t overlayStart = opaque ? SPR_RCT1_WATER_OVERLAY : SPR_WATER_OVERLAY; + PaintAttachToPreviousPS(session, overlayStart + image_offset, 0, 0); if (!(session->ViewFlags & VIEWPORT_FLAG_HIDE_VERTICAL)) { diff --git a/src/openrct2/paint/tile_element/Paint.Surface.h b/src/openrct2/paint/tile_element/Paint.Surface.h index 6b774390f8..15a7a6793e 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.h +++ b/src/openrct2/paint/tile_element/Paint.Surface.h @@ -100,6 +100,9 @@ enum SPR_TERRAIN_PATTERN_MARTIAN = 28995, SPR_TERRAIN_PATTERN_GRASS_CLUMPS = 29001, SPR_TERRAIN_PATTERN_ICE = 29007, + + SPR_RCT1_WATER_MASK = SPR_CSG_BEGIN + 46787, + SPR_RCT1_WATER_OVERLAY = SPR_CSG_BEGIN + 46792, }; #endif //_PAINT_SURFACE_H From 8f6713a4f1ca4b0acbd8d345a612f07a5e15408e Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 24 May 2021 16:54:30 +0200 Subject: [PATCH 15/16] Reverse option, add shortcut --- data/language/en-GB.txt | 2 +- src/openrct2-ui/input/ShortcutIds.h | 1 + src/openrct2-ui/input/Shortcuts.cpp | 10 ++++++++++ src/openrct2-ui/windows/TopToolbar.cpp | 14 +++++++------- src/openrct2/config/Config.cpp | 4 ++-- src/openrct2/config/Config.h | 2 +- src/openrct2/interface/Viewport.h | 1 - src/openrct2/localisation/StringIds.h | 2 +- src/openrct2/paint/tile_element/Paint.Surface.cpp | 4 ++-- 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 39507e0a40..27fcb030f7 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3682,7 +3682,7 @@ STR_6436 :Toggle invisibility STR_6437 :Invisible STR_6438 :I STR_6439 :Tile Inspector: Toggle invisibility -STR_6440 :Opaque water +STR_6440 :Transparent water ############# # Scenarios # diff --git a/src/openrct2-ui/input/ShortcutIds.h b/src/openrct2-ui/input/ShortcutIds.h index 6220a7338a..4facaa43ba 100644 --- a/src/openrct2-ui/input/ShortcutIds.h +++ b/src/openrct2-ui/input/ShortcutIds.h @@ -69,6 +69,7 @@ namespace OpenRCT2::Ui::ShortcutId // View / toggle constexpr std::string_view ViewToggleUnderground = "view.toggle.show_underground"; + constexpr std::string_view ViewToggleTransparentWater = "view.toggle.transparent_water"; constexpr std::string_view ViewToggleBaseLand = "view.toggle.hide_base_land"; constexpr std::string_view ViewToggleVerticalLand = "view.toggle.hide_vertical_land"; constexpr std::string_view ViewToggleRides = "view.toggle.transparent_rides"; diff --git a/src/openrct2-ui/input/Shortcuts.cpp b/src/openrct2-ui/input/Shortcuts.cpp index 6f61b58bb6..6e604ec79b 100644 --- a/src/openrct2-ui/input/Shortcuts.cpp +++ b/src/openrct2-ui/input/Shortcuts.cpp @@ -704,6 +704,15 @@ static void ShortcutConstructionDemolishCurrent() } } +static void ShortcutToggleTransparentWater() +{ + if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) + return; + + gConfigGeneral.transparent_water ^= 1; + config_save_default(); +} + #pragma endregion using namespace OpenRCT2::Ui; @@ -817,6 +826,7 @@ void ShortcutManager::RegisterDefaultShortcuts() RegisterShortcut(ShortcutId::ViewScrollDown, STR_SHORTCUT_SCROLL_MAP_DOWN, "DOWN", []() { }); RegisterShortcut(ShortcutId::ViewToggleUnderground, STR_SHORTCUT_UNDERGROUND_VIEW_TOGGLE, "1", []() { ToggleViewFlag(VIEWPORT_FLAG_UNDERGROUND_INSIDE); }); + RegisterShortcut(ShortcutId::ViewToggleTransparentWater, STR_VIEWPORT_TRANSPARENT_WATER, "2", []() { ShortcutToggleTransparentWater(); }); RegisterShortcut(ShortcutId::ViewToggleBaseLand, STR_SHORTCUT_REMOVE_BASE_LAND_TOGGLE, "H", []() { ToggleViewFlag(VIEWPORT_FLAG_HIDE_BASE); }); RegisterShortcut(ShortcutId::ViewToggleVerticalLand, STR_SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE, "V", []() { ToggleViewFlag(VIEWPORT_FLAG_HIDE_VERTICAL); }); RegisterShortcut(ShortcutId::ViewToggleRides, STR_SHORTCUT_SEE_THROUGH_RIDES_TOGGLE, "3", []() { ToggleViewFlag(VIEWPORT_FLAG_SEETHROUGH_RIDES); }); diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index ff57dc0db5..da35ed1125 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -127,7 +127,7 @@ enum FILE_MENU_DDIDX { enum TOP_TOOLBAR_VIEW_MENU_DDIDX { DDIDX_UNDERGROUND_INSIDE = 0, - DDIDX_OPAQUE_WATER = 1, + DDIDX_TRANSPARENT_WATER = 1, DDIDX_HIDE_BASE = 2, DDIDX_HIDE_VERTICAL = 3, // separator @@ -3612,7 +3612,7 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) using namespace Dropdown; constexpr Item items[] = { ToggleOption(DDIDX_UNDERGROUND_INSIDE, STR_UNDERGROUND_VIEW), - ToggleOption(DDIDX_OPAQUE_WATER, STR_VIEWPORT_OPAQUE_WATER), + ToggleOption(DDIDX_TRANSPARENT_WATER, STR_VIEWPORT_TRANSPARENT_WATER), ToggleOption(DDIDX_HIDE_BASE, STR_REMOVE_BASE_LAND), ToggleOption(DDIDX_HIDE_VERTICAL, STR_REMOVE_VERTICAL_FACES), Separator(), @@ -3642,8 +3642,8 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) rct_viewport* mainViewport = window_get_main()->viewport; if (mainViewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE) Dropdown::SetChecked(DDIDX_UNDERGROUND_INSIDE, true); - if (gConfigGeneral.opaque_water) - Dropdown::SetChecked(DDIDX_OPAQUE_WATER, true); + if (gConfigGeneral.transparent_water) + Dropdown::SetChecked(DDIDX_TRANSPARENT_WATER, true); if (mainViewport->flags & VIEWPORT_FLAG_HIDE_BASE) Dropdown::SetChecked(DDIDX_HIDE_BASE, true); if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VERTICAL) @@ -3674,7 +3674,7 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) // Opaque water relies on RCT1 sprites. if (!is_csg_loaded()) { - Dropdown::SetDisabled(DDIDX_OPAQUE_WATER, true); + Dropdown::SetDisabled(DDIDX_TRANSPARENT_WATER, true); } } @@ -3692,8 +3692,8 @@ static void top_toolbar_view_menu_dropdown(int16_t dropdownIndex) case DDIDX_UNDERGROUND_INSIDE: w->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE; break; - case DDIDX_OPAQUE_WATER: - gConfigGeneral.opaque_water ^= 1; + case DDIDX_TRANSPARENT_WATER: + gConfigGeneral.transparent_water ^= 1; config_save_default(); break; case DDIDX_HIDE_BASE: diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 1a1ff0b5b7..e29069d377 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -227,7 +227,7 @@ namespace Config model->show_real_names_of_guests = reader->GetBoolean("show_real_names_of_guests", true); model->allow_early_completion = reader->GetBoolean("allow_early_completion", false); model->transparent_screenshot = reader->GetBoolean("transparent_screenshot", true); - model->opaque_water = reader->GetBoolean("opaque_water", false); + model->transparent_water = reader->GetBoolean("transparent_water", true); model->last_version_check_time = reader->GetInt64("last_version_check_time", 0); } } @@ -305,7 +305,7 @@ namespace Config writer->WriteBoolean("allow_early_completion", model->allow_early_completion); writer->WriteEnum("virtual_floor_style", model->virtual_floor_style, Enum_VirtualFloorStyle); writer->WriteBoolean("transparent_screenshot", model->transparent_screenshot); - writer->WriteBoolean("opaque_water", model->opaque_water); + writer->WriteBoolean("transparent_water", model->transparent_water); writer->WriteInt64("last_version_check_time", model->last_version_check_time); } diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index 3f516dd0d2..083b2f029e 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -58,7 +58,7 @@ struct GeneralConfiguration bool disable_lightning_effect; bool show_guest_purchases; bool transparent_screenshot; - bool opaque_water; + bool transparent_water; // Localisation int32_t language; diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 8393b1628d..cc4750ab6a 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -49,7 +49,6 @@ enum VIEWPORT_FLAG_CLIP_VIEW = (1 << 17), VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES = (1 << 18), VIEWPORT_FLAG_TRANSPARENT_BACKGROUND = (1 << 19), - VIEWPORT_FLAG_OPAQUE_WATER = (1 << 20), }; enum class ViewportInteractionItem : uint8_t diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 3118b5a81e..94b2634465 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3941,7 +3941,7 @@ enum STR_TILE_INSPECTOR_INVISIBLE_SHORT = 6438, STR_SHORTCUT_TOGGLE_INVISIBILITY = 6439, - STR_VIEWPORT_OPAQUE_WATER = 6440, + STR_VIEWPORT_TRANSPARENT_WATER = 6440, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings diff --git a/src/openrct2/paint/tile_element/Paint.Surface.cpp b/src/openrct2/paint/tile_element/Paint.Surface.cpp index 3285a519db..7e3984b229 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.cpp +++ b/src/openrct2/paint/tile_element/Paint.Surface.cpp @@ -1315,8 +1315,8 @@ void surface_paint(paint_session* session, uint8_t direction, uint16_t height, c | EnumValue(FilterPaletteID::PaletteWater) << 19; PaintAddImageAsParent(session, image_id, 0, 0, 32, 32, -1, waterHeight); - const bool opaque = (gConfigGeneral.opaque_water) && !(session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE); - const uint32_t overlayStart = opaque ? SPR_RCT1_WATER_OVERLAY : SPR_WATER_OVERLAY; + const bool transparent = gConfigGeneral.transparent_water || (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE); + const uint32_t overlayStart = transparent ? SPR_WATER_OVERLAY : SPR_RCT1_WATER_OVERLAY; PaintAttachToPreviousPS(session, overlayStart + image_offset, 0, 0); if (!(session->ViewFlags & VIEWPORT_FLAG_HIDE_VERTICAL)) From 74ef3125333416431ec4c8f156364e47d948cabf Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 24 May 2021 17:07:48 +0200 Subject: [PATCH 16/16] Also make the water splash use opaque water --- .../ride/coaster/WoodenRollerCoaster.cpp | 77 ++++++++++--------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/openrct2/ride/coaster/WoodenRollerCoaster.cpp b/src/openrct2/ride/coaster/WoodenRollerCoaster.cpp index 69e8180c98..f7c74c023d 100644 --- a/src/openrct2/ride/coaster/WoodenRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/WoodenRollerCoaster.cpp @@ -7,10 +7,12 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "../../config/Config.h" #include "../../drawing/Drawing.h" #include "../../interface/Viewport.h" #include "../../paint/Paint.h" #include "../../paint/Supports.h" +#include "../../paint/tile_element/Paint.Surface.h" #include "../../paint/tile_element/Paint.TileElement.h" #include "../../sprites.h" #include "../../world/Map.h" @@ -6082,6 +6084,9 @@ static void wooden_rc_track_water_splash( paint_session* session, ride_id_t rideIndex, uint8_t trackSequence, uint8_t direction, int32_t height, const TileElement* tileElement) { + const bool transparent = gConfigGeneral.transparent_water || (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE); + const uint32_t waterOverlay = transparent ? SPR_WATER_OVERLAY : SPR_RCT1_WATER_OVERLAY; + switch (trackSequence) { case 0: @@ -6093,9 +6098,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24855, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23997, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6113,9 +6118,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24856, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23998, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6133,9 +6138,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24853, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23995, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6153,9 +6158,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24854, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23996, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6182,9 +6187,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24843, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23985, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6202,9 +6207,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24844, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23986, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6222,9 +6227,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24841, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23983, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6242,9 +6247,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24842, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23984, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6271,9 +6276,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24865, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 24003, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6292,9 +6297,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24866, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 24004, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6320,9 +6325,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24841, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23983, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6340,9 +6345,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24842, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23984, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6360,9 +6365,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24843, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23985, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6380,9 +6385,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24844, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23986, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6408,9 +6413,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24853, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23995, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6428,9 +6433,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24854, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23996, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6448,9 +6453,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24855, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23997, 0, 0, 32, 25, 2, height, 0, 3, height); @@ -6468,9 +6473,9 @@ static void wooden_rc_track_water_splash( PaintAddImageAsChildRotated( session, direction, wooden_rc_get_rails_colour(session) | 24856, 0, 0, 32, 25, 2, height, 0, 3, height); PaintAddImageAsChildRotated( - session, direction, 0x61000000 | 5048, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x61000000 | SPR_WATER_MASK, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( - session, direction, 0x00000000 | 5053, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); + session, direction, 0x00000000 | waterOverlay, 0, 0, 32, 25, 2, height + 16, 0, 3, height + 16); PaintAddImageAsChildRotated( session, direction, session->TrackColours[SCHEME_SUPPORTS] | 23998, 0, 0, 32, 25, 2, height, 0, 3, height);