From 7af9992ca81c699bc1cf05eb691e284bf424f050 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Mon, 18 Apr 2022 17:54:29 -0700 Subject: Changeset: 9 Implement IresSpritesheet --- source/Sprite.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 4 deletions(-) (limited to 'source/Sprite.cpp') 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 +#include #include #include @@ -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::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(); - if (!atlas->InitFromFile(spritesheetFile.c_str())) { + if (atlas->InitFromFile(path) != Texture::EC_Success) { return nullptr; } auto sprite = std::make_unique(); 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) -- cgit v1.2.3-70-g09d2