aboutsummaryrefslogtreecommitdiff
path: root/source/Ires.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Ires.cpp')
-rw-r--r--source/Ires.cpp180
1 files changed, 139 insertions, 41 deletions
diff --git a/source/Ires.cpp b/source/Ires.cpp
index 6b161d4..f60fcb7 100644
--- a/source/Ires.cpp
+++ b/source/Ires.cpp
@@ -7,6 +7,7 @@
#include "Material.hpp"
#include "RapidJsonHelper.hpp"
#include "ScopeGuard.hpp"
+#include "Shader.hpp"
#include "Sprite.hpp"
#include "Texture.hpp"
#include "Utils.hpp"
@@ -16,8 +17,10 @@
#include <rapidjson/document.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/filewritestream.h>
+#include <rapidjson/prettywriter.h>
#include <rapidjson/writer.h>
#include <algorithm>
+#include <cassert>
namespace fs = std::filesystem;
using namespace std::literals;
@@ -29,6 +32,7 @@ IresObject::IresObject(Kind kind)
std::string_view IresObject::ToString(Kind kind) {
switch (kind) {
case KD_Texture: return BRUSSEL_TAG_PREFIX_Ires "Texture"sv;
+ case KD_Shader: return BRUSSEL_TAG_PREFIX_Ires "Shader"sv;
case KD_Material: return BRUSSEL_TAG_PREFIX_Ires "Material"sv;
case KD_SpriteFiles: return BRUSSEL_TAG_PREFIX_Ires "SpriteFiles"sv;
case KD_Spritesheet: return BRUSSEL_TAG_PREFIX_Ires "Spritesheet"sv;
@@ -39,6 +43,7 @@ std::string_view IresObject::ToString(Kind kind) {
IresObject::Kind IresObject::FromString(std::string_view name) {
if (name == BRUSSEL_TAG_PREFIX_Ires "Texture"sv) return KD_Texture;
+ if (name == BRUSSEL_TAG_PREFIX_Ires "Shader"sv) return KD_Shader;
if (name == BRUSSEL_TAG_PREFIX_Ires "Material"sv) return KD_Material;
if (name == BRUSSEL_TAG_PREFIX_Ires "SpriteFiles"sv) return KD_SpriteFiles;
if (name == BRUSSEL_TAG_PREFIX_Ires "Spritesheet"sv) return KD_Spritesheet;
@@ -48,6 +53,7 @@ IresObject::Kind IresObject::FromString(std::string_view name) {
std::unique_ptr<IresObject> IresObject::Create(Kind kind) {
switch (kind) {
case KD_Texture: return std::make_unique<IresTexture>();
+ case KD_Shader: return std::make_unique<IresShader>();
case KD_Material: return std::make_unique<IresMaterial>();
case KD_SpriteFiles: return std::make_unique<IresSpriteFiles>();
case KD_Spritesheet: return std::make_unique<IresSpritesheet>();
@@ -68,6 +74,10 @@ void IresObject::SetName(std::string name) {
}
}
+void IresObject::ShowNullName(EditorInstance& editor, Kind kind) {
+ ImGui::Text("<null>");
+}
+
void IresObject::ShowName() const {
if (IsAnnoymous()) {
ImGui::Text("<annoymous %p>", (void*)this);
@@ -84,6 +94,13 @@ void IresObject::ShowFullName() const {
}
}
+void IresObject::ShowNullReference(EditorInstance& editor, Kind kind) {
+ ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
+ ImGui::Text("<null>");
+ ImGui::PopStyleColor();
+ ImGui::AddUnderLine(ImGui::GetStyle().Colors[ImGuiCol_Button]);
+}
+
void IresObject::ShowReference(EditorInstance& editor) {
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
if (IsAnnoymous()) {
@@ -119,16 +136,29 @@ void IresObject::ShowEditor(EditorInstance& editor) {
}
}
-void IresObject::WriteFull(IresObject* ires, rapidjson::Value& value, rapidjson::Document& root) {
+void IresObject::WriteFull(IresWritingContext& ctx, IresObject* ires, rapidjson::Value& value, rapidjson::Document& root) {
rapidjson::Value rvIres(rapidjson::kObjectType);
- ires->Write(rvIres, root);
+ ires->Write(ctx, rvIres, root);
value.AddMember("Type", rapidjson::StringRef(ToString(ires->GetKind())), root.GetAllocator());
value.AddMember("Uid", ires->mUid.Write(root), root.GetAllocator());
value.AddMember("Value", rvIres, root.GetAllocator());
}
-std::unique_ptr<IresObject> IresObject::ReadFull(const rapidjson::Value& value) {
+std::unique_ptr<IresObject> IresObject::ReadFull(IresLoadingContext& ctx, const rapidjson::Value& value) {
+ auto ires = ReadBasic(value);
+ if (!ires) {
+ return nullptr;
+ }
+
+ if (!ReadPartial(ctx, ires.get(), value)) {
+ return nullptr;
+ }
+
+ return ires;
+}
+
+std::unique_ptr<IresObject> IresObject::ReadBasic(const rapidjson::Value& value) {
auto rvType = rapidjson::GetProperty(value, rapidjson::kStringType, "Type"sv);
if (!rvType) return nullptr;
auto kind = FromString(rapidjson::AsStringView(*rvType));
@@ -139,24 +169,20 @@ std::unique_ptr<IresObject> IresObject::ReadFull(const rapidjson::Value& value)
if (!rvUid) return nullptr;
ires->mUid.Read(*rvUid);
- if (!ReadPartial(ires.get(), value)) {
- return nullptr;
- }
-
return ires;
}
-bool IresObject::ReadPartial(IresObject* ires, const rapidjson::Value& value) {
+bool IresObject::ReadPartial(IresLoadingContext& ctx, IresObject* ires, const rapidjson::Value& value) {
auto rvValue = rapidjson::GetProperty(value, "Value"sv);
if (!rvValue) return false;
- ires->Read(*rvValue);
+ ires->Read(ctx, *rvValue);
return true;
}
-void IresObject::Write(rapidjson::Value& value, rapidjson::Document& root) const {
+void IresObject::Write(IresWritingContext& ctx, rapidjson::Value& value, rapidjson::Document& root) const {
}
-void IresObject::Read(const rapidjson::Value& value) {
+void IresObject::Read(IresLoadingContext& ctx, const rapidjson::Value& value) {
}
void IresManager::DiscoverFilesDesignatedLocation() {
@@ -165,8 +191,38 @@ void IresManager::DiscoverFilesDesignatedLocation() {
}
void IresManager::DiscoverFiles(const fs::path& dir) {
- // NOTE: by default does not follow symlinks
- // for (auto& item : fs::recursive_directory_iterator(dir)) {
+ struct LoadCandidate {
+ fs::path path;
+ rapidjson::Document data;
+ RcPtr<IresObject> ires;
+ };
+
+ class IresLoadTimeContext final : public IresLoadingContext {
+ public:
+ // NOTE: pointer stability required
+ robin_hood::unordered_node_map<Uid, LoadCandidate> candidates;
+ std::vector<std::vector<LoadCandidate*>> candidatesByKind;
+
+ IresLoadTimeContext() {
+ candidatesByKind.resize(IresObject::KD_COUNT);
+ }
+
+ std::vector<LoadCandidate*>& GetByKind(IresObject::Kind kind) {
+ int i = static_cast<int>(kind);
+ return candidatesByKind[i];
+ }
+
+ virtual IresObject* FindIres(const Uid& uid) const override {
+ auto iter = candidates.find(uid);
+ if (iter != candidates.end()) {
+ auto& cand = iter->second;
+ return cand.ires.Get();
+ } else {
+ return nullptr;
+ }
+ }
+ } ctx;
+
for (auto& item : fs::directory_iterator(dir)) {
if (!item.is_regular_file()) {
continue;
@@ -175,9 +231,62 @@ void IresManager::DiscoverFiles(const fs::path& dir) {
continue;
}
- auto ires = Load(item.path());
+ auto file = Utils::OpenCstdioFile(item.path(), Utils::Read);
+ if (!file) {
+ fprintf(stderr, "Ires file [" PLATFORM_PATH_STR "] Failed to open file.", item.path().c_str());
+ continue;
+ }
+ DEFER { fclose(file); };
+
+ char readerBuffer[65536];
+ rapidjson::FileReadStream stream(file, readerBuffer, sizeof(readerBuffer));
+
+ rapidjson::Document root;
+ root.ParseStream(stream);
+
+ auto ires = IresObject::ReadBasic(root);
if (!ires) {
- fprintf(stderr, "Failed to load Ires at '" PLATFORM_PATH_STR "'.", item.path().c_str());
+ fprintf(stderr, "Ires file: [" PLATFORM_PATH_STR "] Failed to parse header.", item.path().c_str());
+ continue;
+ }
+
+ // Load name from filename
+ ires->mName = item.path().filename().replace_extension().string();
+ auto& iresName = ires->mName;
+
+ // Load uid should be handled by IresObject::ReadBasic
+ assert(!ires->mUid.IsNull());
+ auto iresUid = ires->GetUid();
+
+ auto iresKind = ires->GetKind();
+
+ auto&& [iter, DISCARD] = ctx.candidates.try_emplace(
+ iresUid,
+ LoadCandidate{
+ .path = item.path(),
+ .data = std::move(root),
+ .ires = RcPtr(ires.release()),
+ });
+ auto& cand = iter->second;
+
+ ctx.GetByKind(iresKind).push_back(&cand);
+ }
+
+ // Load Ires in order by type, there are dependencies between them
+ // TODO full arbitary dependency between Ires
+ for (int i = 0; i < IresObject::KD_COUNT; ++i) {
+ auto kind = static_cast<IresObject::Kind>(i);
+ auto& list = ctx.GetByKind(kind);
+ for (auto cand : list) {
+ auto& ires = cand->ires;
+
+ if (!IresObject::ReadPartial(ctx, ires.Get(), cand->data)) {
+ fprintf(stderr, "Ires file: [" PLATFORM_PATH_STR "] Failed to parse object data.", cand->path.c_str());
+ continue;
+ }
+
+ ires->mMan = this;
+ mObjByUid.try_emplace(ires->GetUid(), ires);
}
}
}
@@ -218,7 +327,7 @@ IresObject* IresManager::Load(const fs::path& filePath) {
rapidjson::Document root;
root.ParseStream(stream);
- auto ires = IresObject::ReadFull(root);
+ auto ires = IresObject::ReadFull(*this, root);
if (!ires) {
return nullptr;
}
@@ -229,32 +338,24 @@ IresObject* IresManager::Load(const fs::path& filePath) {
ires->mName = filePath.filename().replace_extension().string();
Add(ires.get());
- // TODO subdirectory support
-#if 0
- auto iden = fs::path(filePath).replace_extension().lexically_relative(dir).string();
- std::replace(iden.begin(), iden.end(), '\\', '/');
-
- 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
-
return ires.release();
}
+static fs::path GetDesignatedPath(IresObject* ires) {
+ return AppConfig::assetDirPath / "Ires" / fs::path(ires->GetName()).replace_extension(".json");
+}
+
void IresManager::Delete(IresObject* ires) {
// TODO
}
bool IresManager::Rename(IresObject* ires, std::string newName) {
+ auto oldPath = GetDesignatedPath(ires);
ires->mName = std::move(newName);
+ auto newPath = GetDesignatedPath(ires);
+ if (fs::exists(oldPath)) {
+ fs::rename(oldPath, newPath);
+ }
// TODO validate no name duplication
#if 0
@@ -276,10 +377,6 @@ bool IresManager::Rename(IresObject* ires, std::string newName) {
return true;
}
-static fs::path GetDesignatedPath(IresObject* ires) {
- return AppConfig::assetDirPath / "Ires" / fs::path(ires->GetName()).replace_extension(".json");
-}
-
void IresManager::Reload(IresObject* ires) {
auto file = Utils::OpenCstdioFile(GetDesignatedPath(ires), Utils::Read);
if (!file) return;
@@ -291,7 +388,7 @@ void IresManager::Reload(IresObject* ires) {
rapidjson::Document root;
root.ParseStream(stream);
- IresObject::ReadPartial(ires, root);
+ IresObject::ReadPartial(*this, ires, root);
}
void IresManager::Save(IresObject* ires) {
@@ -301,7 +398,7 @@ void IresManager::Save(IresObject* ires) {
void IresManager::Save(IresObject* ires, const fs::path& filePath) {
rapidjson::Document root(rapidjson::kObjectType);
- IresObject::WriteFull(ires, root, root);
+ IresObject::WriteFull(*this, ires, root, root);
auto file = Utils::OpenCstdioFile(filePath, Utils::WriteTruncate);
if (!file) return;
@@ -309,11 +406,12 @@ void IresManager::Save(IresObject* ires, const fs::path& filePath) {
char writerBuffer[65536];
rapidjson::FileWriteStream stream(file, writerBuffer, sizeof(writerBuffer));
- rapidjson::Writer<rapidjson::FileWriteStream> writer(stream);
+ rapidjson::PrettyWriter<rapidjson::FileWriteStream> writer(stream);
+ writer.SetFormatOptions(rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
root.Accept(writer);
}
-IresObject* IresManager::FindIres(const Uid& uid) {
+IresObject* IresManager::FindIres(const Uid& uid) const {
auto iter = mObjByUid.find(uid);
if (iter != mObjByUid.end()) {
return iter->second.Get();