aboutsummaryrefslogtreecommitdiff
path: root/source/Sprite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Sprite.cpp')
-rw-r--r--source/Sprite.cpp163
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
+}