aboutsummaryrefslogtreecommitdiff
path: root/source/Ires.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Ires.cpp')
-rw-r--r--source/Ires.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/source/Ires.cpp b/source/Ires.cpp
new file mode 100644
index 0000000..f700ed6
--- /dev/null
+++ b/source/Ires.cpp
@@ -0,0 +1,176 @@
+#include "Ires.hpp"
+
+#include "AppConfig.hpp"
+#include "RapidJsonHelper.hpp"
+#include "ScopeGuard.hpp"
+#include "Sprite.hpp"
+#include "Texture.hpp"
+#include "Utils.hpp"
+
+#include <rapidjson/document.h>
+#include <rapidjson/filereadstream.h>
+#include <rapidjson/filewritestream.h>
+#include <rapidjson/writer.h>
+#include <algorithm>
+
+namespace fs = std::filesystem;
+using namespace std::literals;
+
+IresObject::IresObject(Kind kind)
+ : mKind{ kind } {
+}
+
+std::string_view IresObject::ToString(Kind kind) {
+ switch (kind) {
+ case KD_Texture: return "Texture"sv;
+ case KD_SpriteFiles: return "SpriteFiles"sv;
+ case KD_Spritesheet: return "Spritesheet"sv;
+ case KD_COUNT: break;
+ }
+ return std::string_view();
+}
+
+IresObject::Kind IresObject::FromString(std::string_view name) {
+ if (name == "Texture"sv) return KD_Texture;
+ if (name == "SpriteFiles"sv) return KD_SpriteFiles;
+ if (name == "Spritesheet"sv) return KD_Spritesheet;
+ return KD_COUNT;
+}
+
+std::unique_ptr<IresObject> IresObject::Create(Kind kind) {
+ switch (kind) {
+ case KD_Texture: return std::make_unique<IresTexture>();
+ case KD_SpriteFiles: return std::make_unique<IresSpriteFiles>();
+ case KD_Spritesheet: return std::make_unique<IresSpritesheet>();
+ case KD_COUNT: break;
+ }
+ return nullptr;
+}
+
+bool IresObject::IsAnnoymous() const {
+ return mName.empty();
+}
+
+rapidjson::Value IresObject::WriteFull(const IresObject& ires, rapidjson::Document& root) {
+ rapidjson::Value rvIres;
+ ires.Write(rvIres, root);
+
+ rapidjson::Value result;
+ result.AddMember("Type", rapidjson::StringRef(ToString(ires.GetKind())), root.GetAllocator());
+ result.AddMember("Value", rvIres, root.GetAllocator());
+ return result;
+}
+
+std::unique_ptr<IresObject> IresObject::ReadFull(const rapidjson::Value& value) {
+ auto rvType = rapidjson::GetProperty(value, rapidjson::kStringType, "Type"sv);
+ if (!rvType) return nullptr;
+ auto kind = FromString(rapidjson::AsStringView(*rvType));
+ auto ires = Create(kind);
+ if (!ires) return nullptr;
+
+ auto rvValue = rapidjson::GetProperty(value, "Value"sv);
+ if (!rvValue) return nullptr;
+ ires->Read(*rvValue);
+
+ return ires;
+}
+
+void IresManager::DiscoverFilesDesignatedLocation() {
+ auto path = AppConfig::assetDirPath / "Ires";
+ DiscoverFiles(path);
+}
+
+void IresManager::DiscoverFiles(const fs::path& dir) {
+ // NOTE: by default does not follow symlinks
+ // for (auto& item : fs::recursive_directory_iterator(dir)) {
+ for (auto& item : fs::directory_iterator(dir)) {
+ if (!item.is_regular_file()) {
+ continue;
+ }
+ if (item.path().extension() != ".json") {
+ continue;
+ }
+
+ auto file = Utils::OpenCstdioFile(item.path(), Utils::Read);
+ if (!file) continue;
+ DEFER { fclose(file); };
+
+ char readerBuffer[65536];
+ rapidjson::FileReadStream stream(file, readerBuffer, sizeof(readerBuffer));
+
+ rapidjson::Document root;
+ root.ParseStream(stream);
+
+ auto ires = IresObject::ReadFull(root);
+ if (!ires) {
+ continue;
+ }
+
+ auto iden = fs::path(item.path()).replace_extension().lexically_relative(dir).string();
+ std::replace(iden.begin(), iden.end(), '\\', '/');
+
+#if 0
+ std::string_view idenView(iden);
+
+ // Trim heading slashes
+ while (idenView.front() == '/') {
+ idenView = std::string_view(idenView.data() + 1, idenView.size());
+ }
+ // Trim trailing slashes
+ while (idenView.back() == '/') {
+ idenView = std::string_view(idenView.data(), idenView.size() - 1);
+ }
+#endif
+ mObjects.try_emplace(std::move(iden), ires.release());
+ }
+}
+
+std::pair<IresObject*, bool> IresManager::Add(IresObject* ires) {
+ auto& name = ires->mName;
+ if (name.empty()) {
+ int n = std::rand();
+ // NOTE: does not include null-terminator
+ int size = snprintf(nullptr, 0, "Unnamed %s #%d", IresObject::ToString(ires->GetKind()).data(), n);
+ name.resize(size); // std::string::resize handles storage for null-terminator alreaedy
+ snprintf(name.data(), size, "Unnamed %s #%d", IresObject::ToString(ires->GetKind()).data(), n);
+ }
+
+ auto [iter, inserted] = mObjects.try_emplace(name, ires);
+ if (inserted) {
+ ires->mMan = this;
+ return { ires, true };
+ } else {
+ return { iter->second.Get(), false };
+ }
+}
+
+void IresManager::Delete(IresObject* ires) {
+ // TODO
+}
+
+bool IresManager::Rename(IresObject* ires, std::string newName) {
+ if (mObjects.contains(newName)) {
+ return false;
+ }
+
+ // Keep the material from being deleted, in case the old entry in map is the only one existing
+ RcPtr rc(ires);
+
+ // Remove old entry (must do before replacing Material::mName, because the std::string_view in the map is a reference to it)
+ mObjects.erase(ires->GetName());
+
+ // Add new entry
+ ires->mName = std::move(newName);
+ mObjects.try_emplace(ires->GetName(), ires);
+
+ return true;
+}
+
+IresObject* IresManager::FindIres(std::string_view path) {
+ auto iter = mObjects.find(path);
+ if (iter != mObjects.end()) {
+ return iter->second.Get();
+ } else {
+ return nullptr;
+ }
+}