From bf7c3931e77a9b4510cd418912e4ff39e9b94159 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 5 Dec 2017 20:35:13 +0000 Subject: [PATCH] Parse images from JSON --- src/openrct2/drawing/Sprite.cpp | 22 ++++++ src/openrct2/object/ImageTable.cpp | 22 +++--- src/openrct2/object/RideObject.cpp | 105 +++++++++++++++++++++++------ 3 files changed, 122 insertions(+), 27 deletions(-) diff --git a/src/openrct2/drawing/Sprite.cpp b/src/openrct2/drawing/Sprite.cpp index 01a5c96078..9e7442ebbc 100644 --- a/src/openrct2/drawing/Sprite.cpp +++ b/src/openrct2/drawing/Sprite.cpp @@ -878,6 +878,28 @@ size_t g1_calculate_data_size(const rct_g1_element * g1) } while (!endOfLine); return ptr - g1->offset; } + else if (g1->flags & G1_FLAG_RLE_COMPRESSION) + { + if (g1->offset == nullptr) + { + return 0; + } + else + { + uint16 * offsets = (uint16 *)g1->offset; + uint8 * ptr = g1->offset + offsets[g1->height - 1]; + bool endOfLine = false; + do + { + uint8 chunk0 = *ptr++; + ptr++; // offset + uint8 chunkSize = chunk0 & 0x7F; + ptr += chunkSize; + endOfLine = (chunk0 & 0x80) != 0; + } while (!endOfLine); + return ptr - g1->offset; + } + } else { return g1->width * g1->height; diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 065cc643a0..0cb48d0d56 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -100,14 +100,20 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) void ImageTable::AddImage(const rct_g1_element * g1) { - auto length = g1_calculate_data_size(g1); - auto dstOffset = _dataSize; - _dataSize += length; - _data = Memory::Reallocate(_data, _dataSize); - auto dst = (uint8 *)((size_t)_data + dstOffset); - Memory::Copy(dst, g1->offset, length); - rct_g1_element newg1 = *g1; - newg1.offset = dst; + auto length = g1_calculate_data_size(g1); + if (length == 0) + { + newg1.offset = 0; + } + else + { + auto dstOffset = _dataSize; + _dataSize += length; + _data = Memory::Reallocate(_data, _dataSize); + auto dst = (uint8 *)((size_t)_data + dstOffset); + Memory::Copy(dst, g1->offset, length); + newg1.offset = dst; + } _entries.push_back(newg1); } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index d2f881fc0c..18c4f4adbd 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -534,13 +534,87 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } +static std::vector ParseRange(std::string s) +{ + // Currently only supports [###] or [###..###] + std::vector result; + if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') + { + s = s.substr(1, s.length() - 2); + auto parts = String::Split(s, ".."); + if (parts.size() == 1) + { + result.push_back(std::stoi(parts[0])); + } + else + { + auto left = std::stoi(parts[0]); + auto right = std::stoi(parts[1]); + if (left <= right) + { + for (auto i = left; i <= right; i++) + { + result.push_back(i); + } + } + else + { + for (auto i = right; i >= left; i--) + { + result.push_back(i); + } + } + } + } + return result; +} + +static std::vector ParseImages(std::string s) +{ + std::vector result; + if (s.empty()) + { + rct_g1_element emptyg1 = { 0 }; + result.push_back(emptyg1); + } + else if (String::StartsWith(s, "$CSG")) + { + if (is_csg_loaded()) + { + auto range = ParseRange(s.substr(4)); + if (range.size() > 0) + { + for (auto i : range) + { + auto g1 = gfx_get_g1_element(SPR_CSG_BEGIN + i); + result.push_back(*g1); + } + } + } + } + return result; +} + +static std::vector GetJsonStringArray(const json_t * arr) +{ + std::vector result; + if (json_is_array(arr)) + { + auto count = json_array_size(arr); + for (size_t i = 0; i < count; i++) + { + auto element = json_string_value(json_array_get(arr, i)); + result.push_back(element); + } + } + return result; +} + void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); auto rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); auto category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); - sint32 previewImg = 0; - sint32 imageStart = 0; _legacyType.shop_item = SHOP_ITEM_NONE; _legacyType.shop_item_secondary = SHOP_ITEM_NONE; @@ -549,14 +623,10 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) String::Equals(rideType, "toilets")) // object tool should be fixed to generate toilets, not restroom. { _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; - previewImg = SPR_CSG_RIDE_PREVIEW_TOILETS; - imageStart = SPR_CSG_TOILETS_BEGIN; } else if (String::Equals(rideType, "foodstall")) { _legacyType.ride_type[0] = RIDE_TYPE_FOOD_STALL; - previewImg = SPR_CSG_RIDE_PREVIEW_ICE_CREAM_STALL; - imageStart = SPR_CSG_ICE_CREAM_STALL_BEGIN; _legacyType.shop_item = SHOP_ITEM_ICE_CREAM; } _legacyType.ride_type[1] = RIDE_TYPE_NULL; @@ -581,21 +651,18 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) stringTable->SetString(3, 0, "Vehicle"); auto imageTable = GetImageTable(); - - if (is_csg_loaded()) + auto jsonImages = json_object_get(root, "images"); + auto imageElements = GetJsonStringArray(jsonImages); + for (const auto &ie : imageElements) { - for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) + auto images = ParseImages(ie); + for (const auto &g1 : images) { - auto g1 = gfx_get_g1_element(previewImg); - imageTable->AddImage(g1); + imageTable->AddImage(&g1); } - for (int i = 0; i < 6; i++) - { - auto g1 = gfx_get_g1_element(imageStart + i); - imageTable->AddImage(g1); - } - rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; - vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; - vehicle0->base_image_id = 0; } + + rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; + vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; + vehicle0->base_image_id = 0; }