From 73d3e4f0e342a6f2ea58310af0b48bdd8f352eb4 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 21 Sep 2025 00:41:30 +0200 Subject: [PATCH] Change "sprite exportalldat" into "sprite exportobject", take a filename instead of an already loaded DAT --- distribution/changelog.txt | 2 + src/openrct2/CommandLineSprite.cpp | 122 ++++++++++--------- src/openrct2/command_line/SpriteCommands.cpp | 2 +- src/openrct2/object/Object.h | 9 +- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index dc8c05d9f0..8dcb2d5d02 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,8 +1,10 @@ 0.4.27 (in development) ------------------------------------------------------------------------ +- Feature: [#25218] `sprite exportobject` command, which allows extracting images from an object. - Improved: [#2296, #2307] The land tool now takes sloped track and paths into account when modifying land. - Change: [#25161] Revert to the ‘fair ride price’ calculation of vanilla RCT2. - Change: [#25228] [Plugin] The available staff costumes array is now ordered alphabetically by name. +- Removed: [#25225] `sprite exportalldat`, replaced with `sprite exportobject`. - Fix: [#24513] Ride/track designs can now be shifted underground as well. - Fix: [#24682] The scenery window isn't enough to accommodate all tool buttons when there are multiple rows of groups/tabs. - Fix: [#24882] Guests are shown with hats and umbrellas whilst clapping. diff --git a/src/openrct2/CommandLineSprite.cpp b/src/openrct2/CommandLineSprite.cpp index 65d1622e0c..eb87ebaad2 100644 --- a/src/openrct2/CommandLineSprite.cpp +++ b/src/openrct2/CommandLineSprite.cpp @@ -19,6 +19,7 @@ #include "core/String.hpp" #include "drawing/Drawing.h" #include "drawing/ImageImporter.h" +#include "object/ObjectFactory.h" #include "object/ObjectLimits.h" #include "object/ObjectManager.h" #include "object/ObjectRepository.h" @@ -35,6 +36,7 @@ namespace OpenRCT2 { using namespace OpenRCT2::Drawing; + static int32_t CommandLineForSpriteExportObject(const char** argv, int32_t argc); static int32_t CommandLineForSpriteCombine(const char** argv, int32_t argc); class SpriteFile @@ -390,66 +392,9 @@ namespace OpenRCT2 return 1; } - if (String::iequals(argv[0], "exportalldat")) + if (String::iequals(argv[0], "exportobject")) { - if (argc < 3) - { - fprintf(stdout, "usage: sprite exportalldat \n"); - return -1; - } - - const char* datName = argv[1]; - const utf8* outputPath = argv[2]; - auto context = CreateContext(); - context->Initialise(); - - const ObjectRepositoryItem* ori = ObjectRepositoryFindObjectByName(datName); - if (ori == nullptr) - { - fprintf(stderr, "Could not find the object.\n"); - return -1; - } - - const RCTObjectEntry* entry = &ori->ObjectEntry; - const auto* loadedObject = ObjectManagerLoadObject(entry); - if (loadedObject == nullptr) - { - fprintf(stderr, "Unable to load object.\n"); - return -1; - } - auto entryIndex = ObjectManagerGetLoadedObjectEntryIndex(loadedObject); - ObjectType objectType = entry->GetType(); - - auto& objManager = context->GetObjectManager(); - const auto* const metaObject = objManager.GetLoadedObject(objectType, entryIndex); - - if (!Path::CreateDirectory(outputPath)) - { - fprintf(stderr, "Unable to create directory.\n"); - return -1; - } - - const uint32_t maxIndex = metaObject->GetNumImages(); - const int32_t numbers = static_cast(std::floor(std::log10(maxIndex) + 1)); - - std::ostringstream oss; // TODO: Remove when C++20 is enabled and std::format can be used - for (uint32_t spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++) - { - oss << std::setw(numbers) << std::setfill('0') << spriteIndex << ".png"; - auto path = Path::Combine(outputPath, PopStr(oss)); - - const auto& g1 = metaObject->GetImageTable().GetImages()[spriteIndex]; - if (!SpriteImageExport(g1, path)) - { - fprintf(stderr, "Could not export\n"); - return -1; - } - - path = fs::u8path(path).generic_u8string(); - fprintf(stdout, "{ \"path\": \"%s\", \"x\": %d, \"y\": %d }", path.c_str(), g1.x_offset, g1.y_offset); - fprintf(stdout, (spriteIndex + 1 != maxIndex) ? ",\n" : "\n"); - } - return 1; + return CommandLineForSpriteExportObject(argv, argc); } if (String::iequals(argv[0], "create")) @@ -626,6 +571,65 @@ namespace OpenRCT2 return 1; } + static int32_t CommandLineForSpriteExportObject(const char** argv, int32_t argc) + { + if (argc < 3) + { + fprintf(stdout, "usage: sprite exportobject \n"); + return -1; + } + + const char* objectPath = argv[1]; + const utf8* outputPath = argv[2]; + auto context = CreateContext(); + context->Initialise(); + + auto& objectRepository = GetContext()->GetObjectRepository(); + std::unique_ptr metaObject = OpenRCT2::ObjectFactory::CreateObjectFromFile(objectRepository, objectPath, true); + if (metaObject == nullptr) + { + fprintf(stderr, "Could not load the object.\n"); + return -1; + } + + if (!Path::CreateDirectory(outputPath)) + { + fprintf(stderr, "Unable to create output directory.\n"); + return -1; + } + + const auto* imageTableStart = metaObject->GetImageTable().GetImages(); + const uint32_t maxIndex = metaObject->GetNumImages(); + const int32_t numbers = static_cast(std::floor(std::log10(maxIndex) + 1)); + + std::ostringstream oss; // TODO: Remove when C++20 is enabled and std::format can be used + for (uint32_t spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++) + { + oss << std::setw(numbers) << std::setfill('0') << spriteIndex << ".png"; + auto path = Path::Combine(outputPath, PopStr(oss)); + + const auto& g1 = imageTableStart[spriteIndex]; + if (g1.width == 0 || g1.height == 0) + { + fprintf(stdout, "\"\""); + } + else + { + if (!SpriteImageExport(g1, path)) + { + fprintf(stderr, "Could not export\n"); + return -1; + } + + path = fs::u8path(path).generic_u8string(); + fprintf(stdout, "{ \"path\": \"%s\", \"x\": %d, \"y\": %d }", path.c_str(), g1.x_offset, g1.y_offset); + } + + fprintf(stdout, (spriteIndex + 1 != maxIndex) ? ",\n" : "\n"); + } + return 1; + } + static int32_t CommandLineForSpriteCombine(const char** argv, int32_t argc) { if (argc < 4) diff --git a/src/openrct2/command_line/SpriteCommands.cpp b/src/openrct2/command_line/SpriteCommands.cpp index ce7d4a7818..4c0717f05f 100644 --- a/src/openrct2/command_line/SpriteCommands.cpp +++ b/src/openrct2/command_line/SpriteCommands.cpp @@ -43,7 +43,7 @@ namespace OpenRCT2 DefineCommand("details", " [idx]", kSpriteOptions, HandleSprite), DefineCommand("export", " ", kSpriteOptions, HandleSprite), DefineCommand("exportall", " ", kSpriteOptions, HandleSprite), - DefineCommand("exportalldat", " ", kSpriteOptions, HandleSprite), + DefineCommand("exportobject", " ", kSpriteOptions, HandleSprite), kCommandTableEnd }; diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index fae9216340..1143a8f42f 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -208,10 +208,6 @@ namespace OpenRCT2 { return _stringTable; } - ImageTable& GetImageTable() - { - return _imageTable; - } /** * Populates the image and string tables from a JSON object @@ -344,6 +340,11 @@ namespace OpenRCT2 uint32_t LoadImages(); void UnloadImages(); + + ImageTable& GetImageTable() + { + return _imageTable; + } }; #ifdef __WARN_SUGGEST_FINAL_TYPES__ #pragma GCC diagnostic pop