diff options
Diffstat (limited to 'source/Sprite.cpp')
-rw-r--r-- | source/Sprite.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/source/Sprite.cpp b/source/Sprite.cpp new file mode 100644 index 0000000..cb8d327 --- /dev/null +++ b/source/Sprite.cpp @@ -0,0 +1,163 @@ +#include "Sprite.hpp" + +#include "Image.hpp" +#include "RapidJsonHelper.hpp" + +#include <rapidjson/document.h> +#include <memory> + +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<Texture::AtlasSource> 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<Texture>(); + if (atlas->InitAtlas(atlasIn, &atlasOut) != Texture::EC_Success) { + return nullptr; + } + + auto sprite = std::make_unique<Sprite>(); + 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<decltype(spriteFiles)>(*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<Texture>(); + if (!atlas->InitFromFile(spritesheetFile.c_str())) { + return nullptr; + } + + auto sprite = std::make_unique<Sprite>(); + 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 +} |