diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 57aebc9372..3ad92d483a 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -248,6 +248,8 @@ void SetupInUseSelectionFlags() Editor::SetSelectedObject(ObjectType::Music, ride.music, ObjectSelectionFlags::InUse); } + // TODO: peep animation objects + // Apply selected object status for hacked vehicles that may not have an associated ride for (auto* vehicle : TrainManager::View()) { diff --git a/src/openrct2/object/PeepAnimationsObject.cpp b/src/openrct2/object/PeepAnimationsObject.cpp index 18bf6eed99..620a4c677f 100644 --- a/src/openrct2/object/PeepAnimationsObject.cpp +++ b/src/openrct2/object/PeepAnimationsObject.cpp @@ -11,18 +11,38 @@ #include "../Context.h" #include "../PlatformEnvironment.h" +#include "../core/EnumMap.hpp" #include "../core/Guard.hpp" #include "../core/Json.hpp" #include "../peep/PeepAnimations.h" using namespace OpenRCT2; +static const EnumMap animationPeepTypeMap({ + { "guest", AnimationPeepType::Guest }, + { "handyman", AnimationPeepType::Handyman }, + { "mechanic", AnimationPeepType::Mechanic }, + { "security", AnimationPeepType::Security }, + { "entertainer", AnimationPeepType::Entertainer }, +}); + void PeepAnimationsObject::Load() { auto numImages = GetImageTable().GetCount(); - if (numImages != 0) + if (numImages == 0) + return; + + _imageOffsetId = LoadImages(); + + // Set loaded image offsets for all animations + for (auto& group : _animationGroups) { - _imageOffsetId = LoadImages(); + auto& requiredAnimationMap = getAnimationsByPeepType(_peepType); + for (auto& [typeStr, typeEnum] : requiredAnimationMap) + { + group[typeEnum].base_image = _imageOffsetId + group[typeEnum].imageTableOffset; + group[typeEnum].bounds = inferMaxAnimationDimensions(group[typeEnum]); + } } } @@ -35,6 +55,43 @@ void PeepAnimationsObject::ReadJson(IReadObjectContext* context, json_t& root) { Guard::Assert(root.is_object(), "PeepAnimationsObject::ReadJson expects parameter root to be an object"); PopulateTablesFromJson(context, root); + + Guard::Assert(root["peepType"].is_string(), "PeepAnimationsObject::ReadJson expects peepType to be a string"); + _peepType = animationPeepTypeMap[Json::GetString(root["peepType"])]; + + auto& requiredAnimationMap = getAnimationsByPeepType(_peepType); + _animationGroups.clear(); + + Guard::Assert(root["animationGroups"].is_array(), "PeepAnimationsObject::ReadJson expects animationGroups to be an array"); + for (auto& groupJson : root["animationGroups"]) + { + Guard::Assert(groupJson["animations"].is_object(), "PeepAnimationsObject::ReadJson expects animations to be an array"); + + PeepAnimations group{}; + for (auto& [typeStr, typeEnum] : requiredAnimationMap) + { + if (!groupJson["animations"].contains(typeStr)) + { + LOG_ERROR("Required animation does not exist: %s", typeStr); + continue; + } + + // The `.data()` here is a workaround for older versions of nlohmann-json. + // TODO: remove when we no longer support Ubuntu 22.04 (Jammy). + auto& animJson = animations[typeStr.data()]; + + // Store animation sequence in vector + auto sequence = animJson["sequence"].get>(); + + // TODO: simplify + PeepAnimation anim{ kSpriteIdNull, sequence }; + anim.imageTableOffset = Json::GetNumber(animJson["offset"]); + + group[typeEnum] = anim; + } + + _animationGroups.push_back(group); + } } void PeepAnimationsObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const diff --git a/src/openrct2/object/PeepAnimationsObject.h b/src/openrct2/object/PeepAnimationsObject.h index b9cd034317..b9415a61d1 100644 --- a/src/openrct2/object/PeepAnimationsObject.h +++ b/src/openrct2/object/PeepAnimationsObject.h @@ -10,15 +10,17 @@ #pragma once #include "../core/IStream.hpp" +#include "../peep/PeepAnimations.h" #include "Object.h" -#include #include class PeepAnimationsObject final : public Object { private: + OpenRCT2::AnimationPeepType _peepType; ImageIndex _imageOffsetId; + std::vector _animationGroups; public: static constexpr ObjectType kObjectType = ObjectType::PeepAnimations; diff --git a/src/openrct2/peep/PeepAnimations.h b/src/openrct2/peep/PeepAnimations.h index c9f3c2905b..b68f771dd0 100644 --- a/src/openrct2/peep/PeepAnimations.h +++ b/src/openrct2/peep/PeepAnimations.h @@ -14,7 +14,7 @@ #include "../drawing/ImageIndexType.h" #include "../entity/Peep.h" -#include +#include enum class PeepAnimationGroup : uint8_t; enum class PeepAnimationType : uint8_t; @@ -43,12 +43,12 @@ namespace OpenRCT2 { uint32_t base_image; ImageIndex imageTableOffset{}; - std::span frame_offsets; + std::vector frame_offsets; SpriteBounds bounds{}; constexpr PeepAnimation() = default; - PeepAnimation(uint32_t baseImage, std::span frameOffsets) + PeepAnimation(uint32_t baseImage, std::vector frameOffsets) : base_image(baseImage) , frame_offsets(frameOffsets) {