aboutsummaryrefslogtreecommitdiff
path: root/source/Sprite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Sprite.cpp')
-rw-r--r--source/Sprite.cpp137
1 files changed, 133 insertions, 4 deletions
diff --git a/source/Sprite.cpp b/source/Sprite.cpp
index cb8d327..6cd575e 100644
--- a/source/Sprite.cpp
+++ b/source/Sprite.cpp
@@ -1,8 +1,13 @@
#include "Sprite.hpp"
+#include "AppConfig.hpp"
+#include "EditorCore.hpp"
+#include "EditorUtils.hpp"
#include "Image.hpp"
#include "RapidJsonHelper.hpp"
+#include <imgui.h>
+#include <misc/cpp/imgui_stdlib.h>
#include <rapidjson/document.h>
#include <memory>
@@ -69,6 +74,8 @@ void IresSpriteFiles::Write(rapidjson::Value& value, rapidjson::Document& root)
}
void IresSpriteFiles::Read(const rapidjson::Value& value) {
+ InvalidateInstance();
+
auto rvFileList = rapidjson::GetProperty(value, rapidjson::kArrayType, "Sprites"sv);
if (!rvFileList) return;
spriteFiles.clear();
@@ -81,7 +88,11 @@ bool IresSpritesheet::IsValid() const {
sheetHSplit != 0;
}
-void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, int wSplit, int hSplit) {
+void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, const IresSpritesheet* conf) {
+ ResplitSpritesheet(sprite, conf->sheetWSplit, conf->sheetHSplit, conf->frameCountOverride);
+}
+
+void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, int wSplit, int hSplit, int frameCount) {
auto atlas = sprite->GetAtlas();
auto size = atlas->GetInfo().size;
int frameWidth = size.x / wSplit;
@@ -94,6 +105,10 @@ void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, int wSplit, int hSplit)
// Width and height in UV coordinates for each frame
float deltaU = 1.0f / wSplit;
float deltaV = 1.0f / hSplit;
+ int i = 0;
+ if (frameCount < 0) {
+ frameCount = std::numeric_limits<int>::max();
+ }
for (int y = 0; y < hSplit; ++y) {
for (int x = 0; x < wSplit; ++x) {
auto& subregion = sprite->mFrames.emplace_back();
@@ -102,7 +117,13 @@ void IresSpritesheet::ResplitSpritesheet(Sprite* sprite, int wSplit, int hSplit)
subregion.v0 = deltaV * y;
// Bottom right
subregion.u1 = subregion.u0 + deltaU;
- subregion.u1 = subregion.v0 + deltaV;
+ subregion.v1 = subregion.v0 + deltaV;
+
+ if ((i + 1) >= frameCount) {
+ return;
+ }
+
+ ++i;
}
}
}
@@ -112,14 +133,17 @@ Sprite* IresSpritesheet::CreateInstance() const {
return nullptr;
}
+ char path[256];
+ snprintf(path, sizeof(path), "%s/Ires/%s", AppConfig::assetDir.c_str(), spritesheetFile.c_str());
+
auto atlas = std::make_unique<Texture>();
- if (!atlas->InitFromFile(spritesheetFile.c_str())) {
+ if (atlas->InitFromFile(path) != Texture::EC_Success) {
return nullptr;
}
auto sprite = std::make_unique<Sprite>();
sprite->mAtlas.Attach(atlas.release());
- ResplitSpritesheet(sprite.get(), sheetWSplit, sheetHSplit);
+ ResplitSpritesheet(sprite.get(), this);
return sprite.release();
}
@@ -134,16 +158,121 @@ void IresSpritesheet::InvalidateInstance() {
mInstance.Attach(nullptr);
}
+bool IresSpritesheet::IsFrameCountOverriden() const {
+ return frameCountOverride > 0;
+}
+
+int IresSpritesheet::GetFrameCount() const {
+ if (IsFrameCountOverriden()) {
+ return frameCountOverride;
+ } else {
+ return sheetWSplit * sheetHSplit;
+ }
+}
+
+void IresSpritesheet::ShowEditor(EditorInstance& editor) {
+ IresObject::ShowEditor(editor);
+
+ bool doInvalidateInstance = false;
+ auto instance = GetInstance(); // NOTE: may be null
+
+ if (ImGui::Button("View Sprite", instance == nullptr)) {
+ editor.OpenSpriteViewer(instance);
+ }
+
+ if (ImGui::InputText("Spritesheet", &spritesheetFile)) {
+ doInvalidateInstance = true;
+ }
+
+ if (ImGui::InputInt("Horizontal split", &sheetWSplit)) {
+ sheetWSplit = std::max(sheetWSplit, 1);
+ if (instance) IresSpritesheet::ResplitSpritesheet(instance, this);
+ }
+
+ if (ImGui::InputInt("Vertical split", &sheetHSplit)) {
+ sheetHSplit = std::max(sheetHSplit, 1);
+ if (instance) IresSpritesheet::ResplitSpritesheet(instance, this);
+ }
+
+ bool frameCountOverriden = frameCountOverride > 0;
+ if (ImGui::Checkbox("##", &frameCountOverriden)) {
+ if (frameCountOverriden) {
+ frameCountOverride = sheetWSplit * sheetHSplit;
+ } else {
+ frameCountOverride = 0;
+ }
+ }
+ ImGui::SameLine();
+ if (frameCountOverriden) {
+ if (ImGui::InputInt("Frame count", &frameCountOverride)) {
+ frameCountOverride = std::max(frameCountOverride, 1);
+ if (instance) IresSpritesheet::ResplitSpritesheet(instance, this);
+ }
+ } else {
+ int dummy = sheetWSplit * sheetHSplit;
+ ImGui::PushDisabled();
+ ImGui::InputInt("Frame count", &dummy, ImGuiInputTextFlags_ReadOnly);
+ ImGui::PopDisabled();
+ }
+
+ if (instance) {
+ auto atlas = instance->GetAtlas();
+ auto imageSize = Utils::FitImage(atlas->GetInfo().size);
+ auto imagePos = ImGui::GetCursorScreenPos();
+ ImGui::Image((ImTextureID)(uintptr_t)atlas->GetHandle(), imageSize);
+
+ auto drawlist = ImGui::GetWindowDrawList();
+ float deltaX = imageSize.x / sheetWSplit;
+ for (int ix = 0; ix < sheetWSplit + 1; ++ix) {
+ float x = ix * deltaX;
+ ImVec2 start{ imagePos.x + x, imagePos.y };
+ ImVec2 end{ imagePos.x + x, imagePos.y + imageSize.y };
+ drawlist->AddLine(start, end, IM_COL32(255, 255, 0, 255));
+ }
+ float deltaY = imageSize.y / sheetHSplit;
+ for (int iy = 0; iy < sheetHSplit + 1; ++iy) {
+ float y = iy * deltaY;
+ ImVec2 start{ imagePos.x, imagePos.y + y };
+ ImVec2 end{ imagePos.x + imageSize.x, imagePos.y + y };
+ drawlist->AddLine(start, end, IM_COL32(255, 255, 0, 255));
+ }
+
+ int i = sheetWSplit * sheetHSplit;
+ int frameCount = GetFrameCount();
+ for (int y = sheetHSplit - 1; y >= 0; --y) {
+ for (int x = sheetWSplit - 1; x >= 0; --x) {
+ if (i > frameCount) {
+ ImVec2 tl{ imagePos.x + x * deltaX + 1.0f, imagePos.y + y * deltaY + 1.0f };
+ ImVec2 br{ imagePos.x + (x + 1) * deltaX, imagePos.y + (y + 1) * deltaY };
+ drawlist->AddRectFilled(tl, br, IM_COL32(255, 0, 0, 100));
+ }
+ --i;
+ }
+ }
+ } else {
+ ImGui::TextUnformatted("Sprite configuration invalid");
+ }
+
+ if (doInvalidateInstance) {
+ InvalidateInstance();
+ }
+}
+
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());
+ if (frameCountOverride > 0) {
+ value.AddMember("FrameCount", frameCountOverride, root.GetAllocator());
+ }
}
void IresSpritesheet::Read(const rapidjson::Value& value) {
+ InvalidateInstance();
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 );
+ BRUSSEL_JSON_GET_DEFAULT(value, "FrameCount", int, frameCountOverride, 0);
}
SpriteMesh::SpriteMesh(Sprite* sprite)