From 829ca1bbb55f71dc147876923dc5cb12171a4e73 Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Wed, 6 Jul 2022 17:55:28 -0400 Subject: [PATCH] World object and Entities can be serialized and deserialized --- docs/tasks/core.todo | 2 +- docs/tasks/editor.todo | 10 +- src/assets/serializing/json_serializable.h | 8 +- src/run_modes/editor/contents/World.cpp | 73 +++++++++++--- .../editor/contents/content_manager.cpp | 9 +- .../editor/contents/content_manager.h | 2 +- src/run_modes/editor/contents/tile_set.cpp | 10 +- src/run_modes/editor/contents/tile_set.h | 8 +- src/run_modes/editor/contents/world.h | 11 ++- src/run_modes/editor/editor.cpp | 6 ++ src/run_modes/editor/panels/asset_browser.cpp | 14 ++- src/run_modes/editor/panels/asset_browser.h | 3 + src/run_modes/editor/panels/world_tree.cpp | 3 +- src/run_modes/editor/panels/world_tree.h | 3 - src/world/components.h | 7 +- src/world/entity.cpp | 94 +++++++++++++++++++ src/world/entity.h | 11 ++- src/world/world.cpp | 76 +++++++++++++++ src/world/world.h | 11 ++- 19 files changed, 306 insertions(+), 55 deletions(-) diff --git a/docs/tasks/core.todo b/docs/tasks/core.todo index 78618fb..a36b5bc 100644 --- a/docs/tasks/core.todo +++ b/docs/tasks/core.todo @@ -15,7 +15,7 @@ Core: ✔ Wrap NFD in an API in the platform module @low @done(22-05-31 15:44) Wrapper added to utils - not platform ✔ Add custom (64 bit?) UUID generator (based on Chreno's UUIDs) @done(22-06-27 13:34) - ☐ Allow Entities to have children @medium + ✔ Allow Entities to have children @medium @done(22-07-06 17:54) ✔ Add Terminal subsystem to allow for printing colored text in a cross-platform way @done(22-05-16 18:05) ✔ Create a LogListener that uses the colored text (replace the current stdout listener) @done(22-05-16 18:23) ✔ Replace XML with JSON (https://github.com/nlohmann/json) @high @done(22-05-19 15:35) diff --git a/docs/tasks/editor.todo b/docs/tasks/editor.todo index 1c3e257..f24314f 100644 --- a/docs/tasks/editor.todo +++ b/docs/tasks/editor.todo @@ -1,5 +1,7 @@ Editor: + ☐ Save and unload world data when a new world is selected + ✔ Load the selected world when double clicked on in the asset browser @done(22-07-05 14:29) ✔ Asset Location MUST be relative to the project root directory @critical @done(22-05-20 18:35) ✔ Switch to NFD dialogs @done(22-05-20 18:35) ✔ Come up with project directory structure @done (9/17/2021, 6:46:44 PM) @@ -7,9 +9,9 @@ Editor: ✔ Implement Run Mode interface class @high @done (2/8/2022, 4:05:17 PM) ✔ Reference raw asset files in a "content" folder@high @done (3/3/2022, 3:15:32 PM) ✔ Platform independant file browsing @done (2/8/2022, 4:05:29 PM) - ☐ Turn World into an editor asset that can be created - ☐ Store entities in the World object - ☐ Implement Saving/loading the World asset + ✔ Turn World into an editor asset that can be created @done(22-07-05 14:04) + ✔ Store entities in the World object @done(22-07-06 17:53) + ✔ Implement Saving/loading the World asset @done(22-07-06 17:53) ☐ Test the Asset Trashing system @high ☐ Add ability to browse and restore trashed assets ✔ Figure out how to make game asset types integrate with editor asset types @critical @done(22-06-27 13:32) @@ -55,7 +57,7 @@ Editor: Properties: - ☐ Implement showing components on selected Entity + ✔ Implement showing components on selected Entity @done(22-07-06 17:53) Tools: Tile Map Editor: diff --git a/src/assets/serializing/json_serializable.h b/src/assets/serializing/json_serializable.h index ae18666..8f1fbf1 100644 --- a/src/assets/serializing/json_serializable.h +++ b/src/assets/serializing/json_serializable.h @@ -17,10 +17,10 @@ namespace lunarium class JSONSerializable { public: - [[nodiscard]] virtual OpRes Serialize(nlohmann::json& node) = 0; - [[nodiscard]] virtual OpRes Deserialize(nlohmann::json& node) = 0; - [[nodiscard]] virtual nlohmann::json AsJSON() = 0; - [[nodiscord]] virtual bool IsValidNode(nlohmann::json& node) = 0; + [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node) = 0; + [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node) = 0; + [[nodiscard]] virtual nlohmann::ordered_json AsJSON() = 0; + [[nodiscord]] virtual bool IsValidNode(nlohmann::ordered_json& node) = 0; }; } diff --git a/src/run_modes/editor/contents/World.cpp b/src/run_modes/editor/contents/World.cpp index ee13a25..ddb1db9 100644 --- a/src/run_modes/editor/contents/World.cpp +++ b/src/run_modes/editor/contents/World.cpp @@ -8,15 +8,18 @@ #include "world.h" #include - +#include #include +#include +#include + namespace lunarium { namespace editor { World::World(std::filesystem::path name) : EditorAsset(AssetType::EATYPE_WORLD), mpWorld(new lunarium::World) { - mLocation = name; + mLocation = name.string() + ".wld"; } World::~World() @@ -29,47 +32,91 @@ namespace lunarium { namespace editor return mpWorld; } + + void World::UnloadWorld() + { + delete mpWorld; + mpWorld = nullptr; + } + + OpRes World::LoadWorld() + { + return LoadRawFile(); + } + OpRes World::LoadRawFile() { return OpRes::OK(); } - OpRes World::Deserialize(nlohmann::json& node) + OpRes World::Deserialize(nlohmann::ordered_json& node) { - // TODO: Implement World::LoadFromJSON - // Create the lunarium::World Object here - // Replace the one created in the constructor #if !BUILD_NO_EDITOR // Only does this when this is an editor build + std::filesystem::path file_path = mAssetDir / mLocation; + std::ifstream ifs = std::ifstream(file_path.string().c_str()); + if (!ifs.is_open()) + { + return OpRes::Fail("Could not open contents file: %s", file_path.string().c_str()); + } + + nlohmann::ordered_json world_file; + ifs >> world_file; + ifs.close(); + + if (mpWorld) + { + mpWorld->Deserialize(world_file).LogIfFailed(Editor::LogCat); + } + #endif return OpRes::OK(); } - OpRes World::Serialize(nlohmann::json& node) + OpRes World::Serialize(nlohmann::ordered_json& node) { - // TODO: Implement World::SaveToJSON - // Store the entities UUID - the Entity class will serialize itself #if !BUILD_NO_EDITOR // Only does this when this is an editor build + nlohmann::ordered_json world_file; + + if (mpWorld) + { + mpWorld->Serialize(world_file).LogIfFailed(Editor::LogCat); + } + + std::filesystem::path file_path = mAssetDir / mLocation; + std::ofstream ofs = std::ofstream(file_path.string().c_str(), std::ios_base::trunc); + if (!ofs.is_open()) + { + return OpRes::Fail("Could not save file: %s", file_path.string().c_str()); + } + + ofs << std::setw(4) << world_file; + ofs.close(); + + #endif return OpRes::OK(); } - bool World::IsValidNode(nlohmann::json& node) + bool World::IsValidNode(nlohmann::ordered_json& node) { + return true; } - nlohmann::json World::AsJSON() + nlohmann::ordered_json World::AsJSON() { #if !BUILD_NO_EDITOR // Only does this when this is an editor build - nlohmann::json node; + nlohmann::ordered_json node; + + Serialize(node).LogIfFailed(Editor::LogCat); return node; #endif - return nlohmann::json(); + return nlohmann::ordered_json(); } }} \ No newline at end of file diff --git a/src/run_modes/editor/contents/content_manager.cpp b/src/run_modes/editor/contents/content_manager.cpp index 511c6d3..fd7ea8e 100644 --- a/src/run_modes/editor/contents/content_manager.cpp +++ b/src/run_modes/editor/contents/content_manager.cpp @@ -70,7 +70,7 @@ namespace lunarium { namespace editor return OpRes::Fail("Could not open contents file: %s", mContentFile.string().c_str()); } - nlohmann::json j; + nlohmann::ordered_json j; ifs >> j; ifs.close(); @@ -175,7 +175,7 @@ namespace lunarium { namespace editor for (auto iter = mAssets.begin(); iter != mAssets.end(); iter++) { EditorAsset* pAsset = iter->second; - nlohmann::json asset; + nlohmann::ordered_json asset; asset["Type"] = (i32)pAsset->GetType(); asset["ID"] = pAsset->GetID(); @@ -184,7 +184,7 @@ namespace lunarium { namespace editor // TODO: This needs to be a relative path! (Relative to the project root) asset["Location"] = pAsset->GetFileLocation().string().c_str(); - if (Failed(pAsset->Serialize(asset).LogIfFailed(Editor::LogCat).LogIfFailed(Editor::LogCat))) + if (Failed(pAsset->Serialize(asset).LogIfFailed(Editor::LogCat))) { return OpRes::Fail("Could not save asset meta data for file: %s", pAsset->GetFileLocation().string().c_str()); } @@ -266,6 +266,7 @@ namespace lunarium { namespace editor return OpRes::Fail("Could not import asset, ID collision. ID: %llu", mNextID); } + asset->mAssetDir = mpProject->GetAssetDirectory(); asset->mID = mNextID; mNextID++; mAssets[asset->mID] = asset; @@ -344,7 +345,7 @@ namespace lunarium { namespace editor Save().LogIfFailed(Editor::LogCat, "Asset was moved"); } - bool ContentManager::IsValidAsset(nlohmann::json& node) + bool ContentManager::IsValidAsset(nlohmann::ordered_json& node) { if (node.is_null()) { return false; } if (node["ID"].is_null()) { return false; } diff --git a/src/run_modes/editor/contents/content_manager.h b/src/run_modes/editor/contents/content_manager.h index 05aeb65..4aeb733 100644 --- a/src/run_modes/editor/contents/content_manager.h +++ b/src/run_modes/editor/contents/content_manager.h @@ -66,7 +66,7 @@ namespace lunarium { namespace editor ContentManager& operator=(const ContentManager&) = delete; private: // Helpers - [[nodiscard]] bool IsValidAsset(nlohmann::json& node); + [[nodiscard]] bool IsValidAsset(nlohmann::ordered_json& node); [[nodiscord]] EditorAsset* CreateAsset(AssetType type); void FreeAssets(); diff --git a/src/run_modes/editor/contents/tile_set.cpp b/src/run_modes/editor/contents/tile_set.cpp index c54a5cb..b140d74 100644 --- a/src/run_modes/editor/contents/tile_set.cpp +++ b/src/run_modes/editor/contents/tile_set.cpp @@ -37,7 +37,7 @@ namespace lunarium { namespace editor return OpRes::OK(); } - OpRes TileSet::Deserialize(nlohmann::json& node) + OpRes TileSet::Deserialize(nlohmann::ordered_json& node) { #if !BUILD_NO_EDITOR // Only does this when this is an editor build @@ -63,7 +63,7 @@ namespace lunarium { namespace editor return OpRes::OK(); } - OpRes TileSet::Serialize(nlohmann::json& node) + OpRes TileSet::Serialize(nlohmann::ordered_json& node) { #if !BUILD_NO_EDITOR // Only does this when this is an editor build @@ -77,9 +77,9 @@ namespace lunarium { namespace editor return OpRes::OK(); } - nlohmann::json TileSet::AsJSON() + nlohmann::ordered_json TileSet::AsJSON() { - nlohmann::json node; + nlohmann::ordered_json node; #if !BUILD_NO_EDITOR // Only does this when this is an editor build @@ -93,7 +93,7 @@ namespace lunarium { namespace editor return node; } - bool TileSet::IsValidNode(nlohmann::json& node) + bool TileSet::IsValidNode(nlohmann::ordered_json& node) { if (node["TileSetID"].is_null()) { return false; } if (!node["TileSetID"].is_number()) { return false; } diff --git a/src/run_modes/editor/contents/tile_set.h b/src/run_modes/editor/contents/tile_set.h index 464cc3a..f1a28c5 100644 --- a/src/run_modes/editor/contents/tile_set.h +++ b/src/run_modes/editor/contents/tile_set.h @@ -24,10 +24,10 @@ namespace lunarium { namespace editor // Load the raw asset file from the internal location OpRes LoadRawFile(); - OpRes Serialize(nlohmann::json& node); - OpRes Deserialize(nlohmann::json& node); - bool IsValidNode(nlohmann::json& node); - nlohmann::json AsJSON(); + OpRes Serialize(nlohmann::ordered_json& node); + OpRes Deserialize(nlohmann::ordered_json& node); + bool IsValidNode(nlohmann::ordered_json& node); + nlohmann::ordered_json AsJSON(); void SetTileSetID(int id); int GetTileSetID() const; diff --git a/src/run_modes/editor/contents/world.h b/src/run_modes/editor/contents/world.h index 88d77c5..1879283 100644 --- a/src/run_modes/editor/contents/world.h +++ b/src/run_modes/editor/contents/world.h @@ -11,6 +11,7 @@ #include "editor_asset.h" +#include #include namespace lunarium @@ -28,12 +29,14 @@ namespace lunarium { namespace editor ~World(); [[nodiscard]] virtual OpRes LoadRawFile(); - [[nodiscard]] virtual OpRes Serialize(nlohmann::json& node); - [[nodiscard]] virtual OpRes Deserialize(nlohmann::json& node); - [[nodiscord]] virtual bool IsValidNode(nlohmann::json& node); - [[nodiscard]] virtual nlohmann::json AsJSON(); + [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node); + [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node); + [[nodiscord]] virtual bool IsValidNode(nlohmann::ordered_json& node); + [[nodiscard]] virtual nlohmann::ordered_json AsJSON(); lunarium::World* GetWorld(); + void UnloadWorld(); + OpRes LoadWorld(); private: // DATA lunarium::World* mpWorld; diff --git a/src/run_modes/editor/editor.cpp b/src/run_modes/editor/editor.cpp index 4b5005b..b4f0241 100644 --- a/src/run_modes/editor/editor.cpp +++ b/src/run_modes/editor/editor.cpp @@ -438,5 +438,11 @@ namespace editor //Logger::Info(Editor::LogCat, "ENTITY SELECT: %ll", (long long) pEnt); ((PropertiesView*)mPanelManager.GetPanel(mPanels.PropertiesView))->SetSelection(pEnt); } + + void Editor::ChangeWorld(lunarium::World* pWorld) + { + // TODO: Unload current world, Load new world + ((WorldTree*)mPanelManager.GetPanel(mPanels.WorldTree))->SetWorld(pWorld); + } } } \ No newline at end of file diff --git a/src/run_modes/editor/panels/asset_browser.cpp b/src/run_modes/editor/panels/asset_browser.cpp index 8a63d35..e072a94 100644 --- a/src/run_modes/editor/panels/asset_browser.cpp +++ b/src/run_modes/editor/panels/asset_browser.cpp @@ -214,8 +214,8 @@ namespace editor if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { - // TODO: Open relevant editor - Logger::Info(Editor::LogCat, "Asset double clicked on. Relevant editor should open!"); + // Logger::Info(Editor::LogCat, "Asset double clicked on. Relevant editor should open!"); + HandleAssetDoubleClick((*iter)); } if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) @@ -333,5 +333,15 @@ namespace editor } + + void AssetBrowser::HandleAssetDoubleClick(EditorAsset* pAsset) + { + if (pAsset->GetType() == AssetType::EATYPE_WORLD) + { + World* pAssetWorld = (World*)pAsset; + mpEditor->ChangeWorld(pAssetWorld->GetWorld()); + } + } + } } diff --git a/src/run_modes/editor/panels/asset_browser.h b/src/run_modes/editor/panels/asset_browser.h index 0d853c7..187fff7 100644 --- a/src/run_modes/editor/panels/asset_browser.h +++ b/src/run_modes/editor/panels/asset_browser.h @@ -19,6 +19,8 @@ namespace lunarium { namespace editor { + class EditorAsset; + class AssetBrowser : public Panel { public: @@ -47,6 +49,7 @@ namespace editor // General Helpers void HandleAssetDrop(std::filesystem::path dir); + void HandleAssetDoubleClick(EditorAsset* pAsset); private: // POPUP ENUMS diff --git a/src/run_modes/editor/panels/world_tree.cpp b/src/run_modes/editor/panels/world_tree.cpp index 9249fe3..0ac4b61 100644 --- a/src/run_modes/editor/panels/world_tree.cpp +++ b/src/run_modes/editor/panels/world_tree.cpp @@ -25,7 +25,7 @@ namespace lunarium mpEditor(editor), // TODO: Temp world created here mpWorld(nullptr), - mDoNewEntity(false), mpSelectedEntity(nullptr) + mpSelectedEntity(nullptr) { AddPopup(PopUp::NEW_ENTITY, "New Entity", [](Panel *p) { @@ -59,6 +59,7 @@ namespace lunarium void WorldTree::SetWorld(lunarium::World *pWorld) { mpWorld = pWorld; + mpSelectedEntity = nullptr; } lunarium::World *WorldTree::GetWorld() diff --git a/src/run_modes/editor/panels/world_tree.h b/src/run_modes/editor/panels/world_tree.h index 3ddfa67..5ead871 100644 --- a/src/run_modes/editor/panels/world_tree.h +++ b/src/run_modes/editor/panels/world_tree.h @@ -38,9 +38,6 @@ namespace editor // Context menus void DoContextMenu(); - // Popup events - bool mDoNewEntity; - void HandlePopupEvents(); void PopupNewEntity(); diff --git a/src/world/components.h b/src/world/components.h index c96dfec..27ffc05 100644 --- a/src/world/components.h +++ b/src/world/components.h @@ -24,9 +24,10 @@ namespace lunarium { std::string Info; - TagComponent() + TagComponent(std::string _info = "") { Info.reserve(256); + Info.insert(0, _info); } }; @@ -36,8 +37,8 @@ namespace lunarium glm::vec3 Rotation = { 0.0f, 0.0f, 0.0f }; glm::vec3 Scale = { 1.0f, 1.0f, 1.0f }; - TransformComponent() - : Position(glm::vec3(0.0f, 0.0f, 0.0f)), Rotation(glm::vec3(0.0f, 0.0f, 0.0f)), Scale(glm::vec3(1.0f, 1.0f, 1.0f)) + TransformComponent(glm::vec3 p = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 r = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 s = glm::vec3(1.0f, 1.0f, 1.0f)) + : Position(p), Rotation(r), Scale(s) { } diff --git a/src/world/entity.cpp b/src/world/entity.cpp index 88263be..2d45c6d 100644 --- a/src/world/entity.cpp +++ b/src/world/entity.cpp @@ -8,6 +8,8 @@ #include "entity.h" #include "world.h" +#include "components.h" +#include namespace lunarium { @@ -45,4 +47,96 @@ namespace lunarium { mChildren.push_back(pChild); } + + + ///////////////////////////////////////////////////////////////////// + // SERIALIZING + ///////////////////////////////////////////////////////////////////// + OpRes Entity::Serialize(nlohmann::ordered_json& node) + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + + node["UUID"] = mUUID; + + auto& components = node["components"]; + if (HasComponent()) + { + nlohmann::ordered_json tag; + tag["type_name"] = "TagComponent"; + tag["info"] = GetComponent().Info; + components.emplace_back(tag); + } + + // TODO: If (HasComponent()) ... + + + // Children + auto& children = node["children"]; + for (int i = 0; i < mChildren.size(); i++) + { + nlohmann::ordered_json child; + mChildren[i]->Serialize(child).LogIfFailed(LogCategory::GAME_SYSTEM); + children.emplace_back(child); + } + + #endif + return OpRes::OK(); + } + + OpRes Entity::Deserialize(nlohmann::ordered_json& node) + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + + mUUID = node["UUID"].get(); + + // TODO: Load components + auto& components = node["components"]; + for (auto iter = components.begin(); iter != components.end(); iter++) + { + auto& comp = *iter; + + std::string comp_type_name = comp["type_name"].get(); + + if ("TagComponent" == comp_type_name) + { + std::string info = comp["info"].get(); + AddComponent(info); + } + } + + // TODO: Load children + auto& children = node["children"]; + for (auto iter = children.begin(); iter != children.end(); iter++) + { + auto& child = *iter; + + Entity* ne = new Entity(mWorld); + ne->Deserialize(child).LogIfFailed(LogCategory::GAME_SYSTEM); + mChildren.push_back(ne); + } + + #endif + return OpRes::OK(); + } + + bool Entity::IsValidNode(nlohmann::ordered_json& node) + { + if (node["UUID"].is_null()) { return false; } + if (!node["UUID"].is_number()) { return false; } + + return true; + } + + nlohmann::ordered_json Entity::AsJSON() + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + nlohmann::ordered_json node; + + Serialize(node).LogIfFailed(LogCategory::GAME_SYSTEM); + + return node; + #endif + + return nlohmann::ordered_json(); + } } \ No newline at end of file diff --git a/src/world/entity.h b/src/world/entity.h index f8cc5c2..005dfb3 100644 --- a/src/world/entity.h +++ b/src/world/entity.h @@ -18,7 +18,7 @@ namespace lunarium // TODO: : public JSONSerializable { - class Entity + class Entity : public JSONSerializable { public: Entity(World& w); @@ -69,10 +69,11 @@ namespace lunarium // TODO: : public JSONSerializable bool HasChildren() const; void AddChild(Entity* pChild); - // TODO: Move to base class - OpRes SaveToJSON(nlohmann::json& node); - OpRes LoadFromJSON(nlohmann::json& node); - OpRes IsNodeValid(nlohmann::json& node); + // Serializing + [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node); + [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node); + [[nodiscord]] virtual bool IsValidNode(nlohmann::ordered_json& node); + [[nodiscard]] virtual nlohmann::ordered_json AsJSON(); private: LUUID mUUID; diff --git a/src/world/world.cpp b/src/world/world.cpp index 918aab7..91fb41c 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -26,6 +26,7 @@ namespace lunarium // } World::World() + : mUUID(UUID::GetNewID()) { } @@ -101,4 +102,79 @@ namespace lunarium return iter == mEntities.end(); } + ///////////////////////////////////////////////////////////////////// + // SERIALIZING + ///////////////////////////////////////////////////////////////////// + OpRes World::Serialize(nlohmann::ordered_json& node) + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + + node["UUID"] = mUUID; + + node["NumberOfEntities"] = mEntities.size(); + auto& ents = node["Entities"]; + for (int i = 0; i < mEntities.size(); i++) + { + nlohmann::ordered_json e; + mEntities[i]->Serialize(e); + ents.emplace_back(e); + } + + #endif + return OpRes::OK(); + } + + OpRes World::Deserialize(nlohmann::ordered_json& node) + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + + mUUID = node["UUID"].get(); + int num_entities = node["NumberOfEntities"].get(); + auto& ents = node["Entities"]; + for (auto it = ents.begin(); it != ents.end(); ++it) + { + auto& ent = (*it); + Entity* new_ent = new Entity(*this); + + if (!new_ent->IsValidNode(ent)) + { + delete new_ent; + return OpRes::Fail("Invalid entity node"); + } + + new_ent->Deserialize(ent); + mEntities.push_back(new_ent); + } + + #endif + return OpRes::OK(); + } + + bool World::IsValidNode(nlohmann::ordered_json& node) + { + if (node["UUID"].is_null()) { return false; } + if (!node["UUID"].is_number()) { return false; } + + if (node["NumberOfEntities"].is_null()) { return false; } + if (!node["NumberOfEntities"].is_number()) { return false; } + + if (node["Entities"].is_null()) { return false; } + + + return false; + } + + nlohmann::ordered_json World::AsJSON() + { + #if !BUILD_NO_EDITOR // Only does this when this is an editor build + nlohmann::ordered_json node; + + Serialize(node).LogIfFailed(LogCategory::GAME_SYSTEM); + + return node; + #endif + + return nlohmann::ordered_json(); + } + } \ No newline at end of file diff --git a/src/world/world.h b/src/world/world.h index 05fa4a4..8ddfad8 100644 --- a/src/world/world.h +++ b/src/world/world.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -38,7 +39,7 @@ namespace lunarium int Index; }; - class World + class World : public JSONSerializable { public: struct Region @@ -72,8 +73,16 @@ namespace lunarium std::vector::iterator EntitiesBegin(); bool EntitiesIsEnd(std::vector::iterator& iter); + // Serializing + [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node); + [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node); + [[nodiscord]] virtual bool IsValidNode(nlohmann::ordered_json& node); + [[nodiscard]] virtual nlohmann::ordered_json AsJSON(); + private: + LUUID mUUID; + std::string mWorldName; entt::registry mECSRegistry; std::vector mEntities;