diff --git a/src/openrct2-ui/windows/AssetPacks.cpp b/src/openrct2-ui/windows/AssetPacks.cpp index 679c15a190..c1294304d0 100644 --- a/src/openrct2-ui/windows/AssetPacks.cpp +++ b/src/openrct2-ui/windows/AssetPacks.cpp @@ -288,6 +288,12 @@ private: { auto& objectManager = GetContext()->GetObjectManager(); objectManager.ResetObjects(); + + auto assetPackManager = GetContext()->GetAssetPackManager(); + if (assetPackManager != nullptr) + { + assetPackManager->SaveEnabledAssetPacks(); + } } }; diff --git a/src/openrct2/AssetPack.h b/src/openrct2/AssetPack.h index 38c89b28af..244d16c3cc 100644 --- a/src/openrct2/AssetPack.h +++ b/src/openrct2/AssetPack.h @@ -31,7 +31,7 @@ namespace OpenRCT2 AudioSampleTable _sampleTable; std::vector _entries; - bool _enabled = true; + bool _enabled; public: fs::path Path; diff --git a/src/openrct2/AssetPackManager.cpp b/src/openrct2/AssetPackManager.cpp index c3eac93282..afffc7f5e3 100644 --- a/src/openrct2/AssetPackManager.cpp +++ b/src/openrct2/AssetPackManager.cpp @@ -12,6 +12,7 @@ #include "AssetPack.h" #include "Context.h" #include "PlatformEnvironment.h" +#include "config/Config.h" #include "core/Console.hpp" #include "core/FileSystem.hpp" #include "core/String.hpp" @@ -41,6 +42,24 @@ AssetPack* AssetPackManager::GetAssetPack(size_t index) return _assetPacks[index].get(); } +AssetPack* AssetPackManager::GetAssetPack(std::string_view id) +{ + auto index = GetAssetPackIndex(id); + if (index != std::numeric_limits::max()) + return _assetPacks[index].get(); + return nullptr; +} + +size_t AssetPackManager::GetAssetPackIndex(std::string_view id) +{ + auto it = std::find_if(_assetPacks.begin(), _assetPacks.end(), [&](const std::unique_ptr& assetPack) { + return assetPack != nullptr ? assetPack->Id == id : false; + }); + if (it == _assetPacks.end()) + return std::numeric_limits::max(); + return std::distance(_assetPacks.begin(), it); +} + void AssetPackManager::Scan() { ClearAssetPacks(); @@ -109,3 +128,71 @@ void AssetPackManager::AddAssetPack(const fs::path& path) Console::Error::WriteFormat("Unable to load asset pack: %s (%s)", fileName.c_str(), e.what()); } } + +template static void EnumerateCommaSeparatedList(std::string_view csl, TFunc func) +{ + size_t elStart = 0; + for (size_t i = 0; i <= csl.size(); i++) + { + if (i == csl.size() || csl[i] == ',') + { + auto el = csl.substr(elStart, i - elStart); + if (el.size() != 0) + func(el); + elStart = i + 1; + } + } +} + +void AssetPackManager::LoadEnabledAssetPacks() +{ + // Re-order asset packs + std::vector> newAssetPacks; + EnumerateCommaSeparatedList(gConfigGeneral.asset_pack_order, [&](std::string_view id) { + auto index = GetAssetPackIndex(id); + if (index != std::numeric_limits::max()) + { + newAssetPacks.push_back(std::move(_assetPacks[index])); + } + }); + for (auto& assetPack : _assetPacks) + { + if (assetPack != nullptr) + { + newAssetPacks.push_back(std::move(assetPack)); + } + } + _assetPacks = std::move(newAssetPacks); + + // Set which asset packs are enabled + EnumerateCommaSeparatedList(gConfigGeneral.enabled_asset_packs, [&](std::string_view id) { + auto assetPack = GetAssetPack(id); + if (assetPack != nullptr) + { + assetPack->SetEnabled(true); + } + }); +} + +void AssetPackManager::SaveEnabledAssetPacks() +{ + u8string orderList; + u8string enabledList; + for (const auto& assetPack : _assetPacks) + { + orderList.append(assetPack->Id); + orderList.push_back(','); + if (assetPack->IsEnabled()) + { + enabledList.append(assetPack->Id); + enabledList.push_back(','); + } + } + if (orderList.size() > 0) + orderList.pop_back(); + if (enabledList.size() > 0) + enabledList.pop_back(); + gConfigGeneral.asset_pack_order = orderList; + gConfigGeneral.enabled_asset_packs = enabledList; + config_save_default(); +} diff --git a/src/openrct2/AssetPackManager.h b/src/openrct2/AssetPackManager.h index 0b3ef120b0..f345cf68b5 100644 --- a/src/openrct2/AssetPackManager.h +++ b/src/openrct2/AssetPackManager.h @@ -32,6 +32,8 @@ namespace OpenRCT2 size_t GetCount() const; AssetPack* GetAssetPack(size_t index); + AssetPack* GetAssetPack(std::string_view id); + size_t GetAssetPackIndex(std::string_view id); void Scan(); void Reload(); @@ -39,6 +41,9 @@ namespace OpenRCT2 void LoadSamplesForObject(std::string_view id, AudioSampleTable& objectTable); + void LoadEnabledAssetPacks(); + void SaveEnabledAssetPacks(); + private: void ClearAssetPacks(); void AddAssetPack(const fs::path& path); diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 0d45df3300..04b265e6e9 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -442,6 +442,7 @@ namespace OpenRCT2 if (!gOpenRCT2Headless) { _assetPackManager->Scan(); + _assetPackManager->LoadEnabledAssetPacks(); _assetPackManager->Reload(); } diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 5fba41ebff..6e90ace5e2 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -214,6 +214,8 @@ namespace Config model->show_guest_purchases = reader->GetBoolean("show_guest_purchases", false); 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->asset_pack_order = reader->GetString("asset_pack_order", ""); + model->enabled_asset_packs = reader->GetString("enabled_asset_packs", ""); model->transparent_screenshot = reader->GetBoolean("transparent_screenshot", true); model->transparent_water = reader->GetBoolean("transparent_water", true); @@ -298,6 +300,8 @@ namespace Config writer->WriteBoolean("show_guest_purchases", model->show_guest_purchases); writer->WriteBoolean("show_real_names_of_guests", model->show_real_names_of_guests); writer->WriteBoolean("allow_early_completion", model->allow_early_completion); + writer->WriteString("asset_pack_order", model->asset_pack_order); + writer->WriteString("enabled_asset_packs", model->enabled_asset_packs); writer->WriteEnum("virtual_floor_style", model->virtual_floor_style, Enum_VirtualFloorStyle); writer->WriteBoolean("transparent_screenshot", model->transparent_screenshot); writer->WriteBoolean("transparent_water", model->transparent_water); diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index 3dd0da7f4b..f1cfdfd7ac 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -105,6 +105,8 @@ struct GeneralConfiguration bool steam_overlay_pause; bool show_real_names_of_guests; bool allow_early_completion; + u8string asset_pack_order; + u8string enabled_asset_packs; // Loading and saving bool confirmation_prompt;