#include "Sprite.hpp" #include "Image.hpp" #include "RapidJsonHelper.hpp" #include #include using namespace std::literals; bool Sprite::IsValid() const { return mAtlas != nullptr; } bool IresSpriteFiles::IsValid() const { return !spriteFiles.empty(); } Sprite* IresSpriteFiles::CreateInstance() const { if (IsValid()) { return nullptr; } std::vector sources; sources.resize(spriteFiles.size()); for (auto& file : spriteFiles) { } Texture::AtlasOutput atlasOut; Texture::AtlasInput atlasIn{ .sources = sources, .packingMode = Texture::PM_KeepSquare, }; atlasIn.sources = sources; auto atlas = std::make_unique(); if (atlas->InitAtlas(atlasIn, &atlasOut) != Texture::EC_Success) { return nullptr; } auto sprite = std::make_unique(); sprite->mAtlas.Attach(atlas.release()); sprite->mBoundingBox = atlasOut.elements[0].subregionSize; sprite->mFrames.reserve(atlasOut.elements.size()); for (auto& elm : atlasOut.elements) { // Validate bounding box if (sprite->mBoundingBox != elm.subregionSize) { return nullptr; } // Copy frame subregion sprite->mFrames.push_back(elm.subregion); } return sprite.release(); } Sprite* IresSpriteFiles::GetInstance() { if (mInstance == nullptr) { mInstance.Attach(CreateInstance()); } return mInstance.Get(); } void IresSpriteFiles::InvalidateInstance() { mInstance.Attach(nullptr); } void IresSpriteFiles::Write(rapidjson::Value& value, rapidjson::Document& root) const { value.AddMember("Sprites", rapidjson::WriteVectorPrimitives(root, spriteFiles.begin(), spriteFiles.end()), root.GetAllocator()); } void IresSpriteFiles::Read(const rapidjson::Value& value) { auto rvFileList = rapidjson::GetProperty(value, rapidjson::kArrayType, "Sprites"sv); if (!rvFileList) return; spriteFiles.clear(); rapidjson::ReadVectorPrimitives(*rvFileList, spriteFiles); } bool IresSpritesheet::IsValid() const { return !spritesheetFile.empty() && sheetWSplit != 0 && sheetHSplit != 0; } void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, int wSplit, int hSplit) { auto atlas = sprite->GetAtlas(); auto size = atlas->GetInfo().size; int frameWidth = size.x / wSplit; int frameHeight = size.y / hSplit; sprite->mBoundingBox = { frameWidth, frameHeight }; sprite->mFrames.clear(); sprite->mFrames.reserve(wSplit * hSplit); // Width and height in UV coordinates for each frame float deltaU = 1.0f / wSplit; float deltaV = 1.0f / hSplit; for (int y = 0; y < hSplit; ++y) { for (int x = 0; x < wSplit; ++x) { auto& subregion = sprite->mFrames.emplace_back(); // Top left subregion.u0 = deltaU * x; subregion.v0 = deltaV * y; // Bottom right subregion.u1 = subregion.u0 + deltaU; subregion.u1 = subregion.v0 + deltaV; } } } Sprite* IresSpritesheet::CreateInstance() const { if (!IsValid()) { return nullptr; } auto atlas = std::make_unique(); if (!atlas->InitFromFile(spritesheetFile.c_str())) { return nullptr; } auto sprite = std::make_unique(); sprite->mAtlas.Attach(atlas.release()); ResplitSpritesheet(sprite.get(), sheetWSplit, sheetHSplit); return sprite.release(); } Sprite* IresSpritesheet::GetInstance() { if (mInstance == nullptr) { mInstance.Attach(CreateInstance()); } return mInstance.Get(); } void IresSpritesheet::InvalidateInstance() { mInstance.Attach(nullptr); } void IresSpritesheet::Write(rapidjson::Value& value, rapidjson::Document& root) const { value.AddMember("SpriteSheet", spritesheetFile, root.GetAllocator()); value.AddMember("WSplit", sheetWSplit, root.GetAllocator()); value.AddMember("HSplit", sheetHSplit, root.GetAllocator()); } void IresSpritesheet::Read(const rapidjson::Value& value) { BRUSSEL_JSON_GET(value, "SpriteSheet", std::string, spritesheetFile, return ); BRUSSEL_JSON_GET(value, "WSplit", int, sheetWSplit, return ); BRUSSEL_JSON_GET(value, "HSplit", int, sheetHSplit, return ); } SpriteMesh::SpriteMesh(Sprite* sprite) : mSprite(sprite) { } void SpriteMesh::SetFrame(int frame) { // TODO } void SpriteMesh::PlayFrame() { // TODO } void SpriteMesh::SetPlaybackSpeed(int speed) { // TODO }