From 971e2dcaa22bc0239f372f7f4a64c714e355767f Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 00:51:13 +0000 Subject: [PATCH] Add JSON loading for walls --- src/openrct2/object/FootpathItemObject.cpp | 43 +---------- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/ObjectJsonHelpers.cpp | 86 +++++++++++++++++++--- src/openrct2/object/ObjectJsonHelpers.h | 2 + src/openrct2/object/WallObject.cpp | 63 +++++++++++++++- src/openrct2/object/WallObject.h | 1 + 6 files changed, 144 insertions(+), 52 deletions(-) diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index fd2b2e4f99..78006e1186 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -96,50 +96,11 @@ static uint8 ParseDrawType(const std::string &s) return PATH_BIT_DRAW_TYPE_LIGHTS; } -static uint8 ParseCursor(const std::string &s) -{ - static const std::unordered_map LookupTable - { - { "CURSOR_BLANK", CURSOR_BLANK }, - { "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, - { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, - { "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, - { "CURSOR_ZZZ", CURSOR_ZZZ }, - { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, - { "CURSOR_PICKER", CURSOR_PICKER }, - { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, - { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, - { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, - { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, - { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, - { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, - { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, - { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, - { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, - { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, - { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, - { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, - { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, - { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, - { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, - { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, - { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, - { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, - { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, - {"CURSOR_ARROW", CURSOR_ARROW }, - }; - - auto result = LookupTable.find(s); - return (result != LookupTable.end()) ? - result->second : - CURSOR_ARROW; -} - void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root) { auto properties = json_object_get(root, "properties"); - _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(json_object_get(properties, "renderAs"))); - _legacyType.path_bit.tool_id = ParseCursor(ObjectJsonHelpers::GetString(json_object_get(properties, "cursor"))); + _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs")); + _legacyType.path_bit.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN); _legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price")); SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index ca5b6b8b89..48fd44d35b 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_wall") return OBJECT_TYPE_WALLS; if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; if (s == "water") return OBJECT_TYPE_WATER; diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index cb7286f3a6..e8519e7885 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -16,11 +16,13 @@ #pragma warning(disable : 4706) // assignment within conditional expression +#include #include "../Context.h" #include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/Path.hpp" #include "../core/String.hpp" +#include "../interface/Cursors.h" #include "../localisation/language.h" #include "../PlatformEnvironment.h" #include "../sprites.h" @@ -47,6 +49,14 @@ namespace ObjectJsonHelpers std::string(); } + std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue) + { + auto value = json_object_get(obj, name.c_str()); + return json_is_string(value) ? + json_string_value(value) : + defaultValue; + } + std::vector GetJsonStringArray(const json_t * arr) { std::vector result; @@ -66,6 +76,45 @@ namespace ObjectJsonHelpers return result; } + uint8 ParseCursor(const std::string &s, uint8 defaultValue) + { + static const std::unordered_map LookupTable + { + { "CURSOR_BLANK", CURSOR_BLANK }, + { "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, + { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, + { "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, + { "CURSOR_ZZZ", CURSOR_ZZZ }, + { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, + { "CURSOR_PICKER", CURSOR_PICKER }, + { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, + { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, + { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, + { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, + { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, + { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, + { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, + { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, + { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, + { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, + { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, + { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, + { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, + { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, + { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, + { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, + { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, + { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, + { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, + { "CURSOR_ARROW", CURSOR_ARROW }, + }; + + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + defaultValue; + } + rct_object_entry ParseObjectEntry(const std::string & s) { rct_object_entry entry = { 0 }; @@ -117,17 +166,36 @@ namespace ObjectJsonHelpers auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); auto objectPath = Path::Combine(objectsPath, name); auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); - auto &imgTable = static_cast(obj)->GetImageTable(); - auto numImages = imgTable.GetCount(); - auto images = imgTable.GetImages(); - for (uint32 i = start; i < Math::Min(numImages, end); i++) + if (obj != nullptr) { - auto g1 = images[i]; - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); - result.push_back(g1); + auto &imgTable = static_cast(obj)->GetImageTable(); + auto numImages = imgTable.GetCount(); + auto images = imgTable.GetImages(); + for (uint32 i = start; i < Math::Min(numImages, end); i++) + { + auto g1 = images[i]; + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); + } + delete obj; + } + else + { + log_warning("Unable to open '%s'", objectPath.c_str()); + } + + // Add place holders + auto placeHolders = (size_t)(end - start) - result.size(); + if (placeHolders > 0) + { + log_warning("Adding %d placeholders", placeHolders); + for (size_t i = 0; i < placeHolders; i++) + { + auto g1 = rct_g1_element{}; + result.push_back(g1); + } } - delete obj; return result; } diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 7cc3c11cb7..28ac029f06 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -31,7 +31,9 @@ namespace ObjectJsonHelpers { bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); + std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue = ""); std::vector GetJsonStringArray(const json_t * arr); + uint8 ParseCursor(const std::string &s, uint8 defaultValue); rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index 4f1ad39de8..0212c7fb9a 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -15,10 +15,11 @@ #pragma endregion #include "../core/IStream.hpp" -#include "WallObject.h" - #include "../drawing/Drawing.h" +#include "../interface/Cursors.h" #include "../localisation/Language.h" +#include "ObjectJsonHelpers.h" +#include "WallObject.h" void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -88,3 +89,61 @@ void WallObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 heigh gfx_draw_sprite(dpi, imageId, x, y, 0); } } + +void WallObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + _legacyType.wall.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN); + _legacyType.wall.height = json_integer_value(json_object_get(properties, "height")); + _legacyType.wall.price = json_integer_value(json_object_get(properties, "price")); + + auto jScrollingMode = json_object_get(properties, "scrollingMode"); + _legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? + json_integer_value(jScrollingMode) : + -1; + + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); + + // Flags + _legacyType.wall.flags = ObjectJsonHelpers::GetFlags(properties, { + { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR }, + { "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR }, + { "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR }, + { "hasGrass", WALL_SCENERY_HAS_GLASS }, + { "isBanner", WALL_SCENERY_IS_BANNER }, + { "isDoor", WALL_SCENERY_IS_DOOR }, + { "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }}); + _legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags(properties, { + { "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, + { "isAnimated", WALL_SCENERY_2_ANIMATED }}); + + // HACK To avoid 'negated' properties in JSON, handle this separately until + // flag is inverted in this code base. + if (!ObjectJsonHelpers::GetBoolean(properties, "isAllowedOnSlope", false)) + { + _legacyType.wall.flags |= WALL_SCENERY_CANT_BUILD_ON_SLOPE; + } + + // HACK WALL_SCENERY_HAS_PRIMARY_COLOUR actually means, has any colour but we simplify the + // JSON and handle this on load. We should change code base in future to reflect the JSON. + if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)) + { + if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) || + (_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR)) + { + _legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR; + } + } + + // Door sound + auto jDoorSound = json_object_get(properties, "scrollingMode"); + if (jDoorSound != nullptr) + { + auto doorSound = json_integer_value(jDoorSound); + _legacyType.wall.flags2 |= (doorSound << WALL_SCENERY_2_DOOR_SOUND_SHIFT) & WALL_SCENERY_2_DOOR_SOUND_MASK; + } + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} diff --git a/src/openrct2/object/WallObject.h b/src/openrct2/object/WallObject.h index 605443e0c0..388685f905 100644 --- a/src/openrct2/object/WallObject.h +++ b/src/openrct2/object/WallObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override;