aboutsummaryrefslogtreecommitdiff
path: root/source/30-game
diff options
context:
space:
mode:
Diffstat (limited to 'source/30-game')
-rw-r--r--source/30-game/EditorAttachmentImpl.cpp4
-rw-r--r--source/30-game/EditorCorePrivate.cpp27
-rw-r--r--source/30-game/GameObject.cpp44
-rw-r--r--source/30-game/GameObject.hpp30
-rw-r--r--source/30-game/Ires.cpp48
-rw-r--r--source/30-game/Ires.hpp34
-rw-r--r--source/30-game/Level.cpp65
-rw-r--r--source/30-game/Level.hpp27
-rw-r--r--source/30-game/Material.cpp10
9 files changed, 181 insertions, 108 deletions
diff --git a/source/30-game/EditorAttachmentImpl.cpp b/source/30-game/EditorAttachmentImpl.cpp
index 62d15eb..b09c133 100644
--- a/source/30-game/EditorAttachmentImpl.cpp
+++ b/source/30-game/EditorAttachmentImpl.cpp
@@ -1,6 +1,8 @@
#include "EditorAttachmentImpl.hpp"
#include "EditorAttachment.hpp"
+#include <Metadata.hpp>
+
EditorAttachment::EditorAttachment() {
}
@@ -15,7 +17,7 @@ std::unique_ptr<EditorAttachment> EaGameObject::Create(GameObject* object) {
default: result = new EaGameObject(); break;
}
- result->name = GameObject::ToString(kind);
+ result->name = Metadata::EnumToString(kind);
result->eulerAnglesRotation = glm::eulerAngles(object->GetRotation());
return std::unique_ptr<EditorAttachment>(result);
}
diff --git a/source/30-game/EditorCorePrivate.cpp b/source/30-game/EditorCorePrivate.cpp
index 9fd6087..43857a8 100644
--- a/source/30-game/EditorCorePrivate.cpp
+++ b/source/30-game/EditorCorePrivate.cpp
@@ -8,13 +8,15 @@
#include "EditorNotification.hpp"
#include "EditorUtils.hpp"
#include "GameObject.hpp"
-#include "Macros.hpp"
#include "Mesh.hpp"
#include "Player.hpp"
#include "SceneThings.hpp"
-#include "ScopeGuard.hpp"
#include "VertexIndex.hpp"
-#include "YCombinator.hpp"
+
+#include <Macros.hpp>
+#include <Metadata.hpp>
+#include <ScopeGuard.hpp>
+#include <YCombinator.hpp>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
@@ -146,9 +148,9 @@ void EditorContentBrowser::Show(bool* open) {
ImGui::OpenPopup("New Ires");
}
if (ImGui::BeginPopup("New Ires")) {
- for (int i = 0; i < IresObject::KD_COUNT; ++i) {
+ for (int i = 0; i < (int)IresObject::KD_COUNT; ++i) {
auto kind = static_cast<IresObject::Kind>(i);
- if (ImGui::MenuItem(IresObject::ToString(kind).data())) {
+ if (ImGui::MenuItem(Metadata::EnumToString(kind).data())) {
auto ires = IresObject::Create(kind);
auto [DISCARD, success] = IresManager::instance->Add(ires.get());
if (success) {
@@ -228,7 +230,7 @@ void EditorContentBrowser::Show(bool* open) {
}
if (!mInspector->renaming) {
if (ImGui::BeginDragDropSource()) {
- auto kindName = IresObject::ToString(ires->GetKind());
+ auto kindName = Metadata::EnumToString(ires->GetKind());
// Reason: intentionally using pointer as payload
ImGui::SetDragDropPayload(kindName.data(), &ires, sizeof(ires)); // NOLINT(bugprone-sizeof-expression)
ImGui::Text("%s '%s'", kindName.data(), name.c_str());
@@ -249,6 +251,11 @@ void EditorContentBrowser::Show(bool* open) {
mInspector->renamingScratchBuffer = ldObj.name;
}
+ if (ImGui::Button("Save", !isIttLevel)) {
+ auto ldObj = static_cast<LevelManager::LoadableObject*>(origItPtr);
+ LevelManager::instance->SaveLevel(ldObj->level->GetUid());
+ }
+
auto& objects = LevelManager::instance->mObjByUid;
for (auto it = objects.begin(); it != objects.end(); ++it) {
auto& uid = it->first;
@@ -779,7 +786,9 @@ void EditorInstance::ShowInspector(LevelManager::LoadableObject* ldObj) {
ImGui::InputText("Name", &ldObj->name);
ImGui::InputTextMultiline("Desciption", &ldObj->description);
- // TODO level object explorer
+ if (ImGui::CollapsingHeader("Instanciation Entries")) {
+ ldObj->level->ShowInstanciationEntries(*this);
+ }
}
void EditorInstance::ShowInspector(GameObject* object) {
@@ -915,7 +924,7 @@ void EditorInstance::ShowInspector(GameObject* object) {
ImGui::SameLine();
IresObject::ShowReferenceSafe(*this, ea->confSprite.Get());
if (ImGui::BeginDragDropTarget()) {
- if (auto payload = ImGui::AcceptDragDropPayload(IresObject::ToString(IresObject::KD_Spritesheet).data())) {
+ if (auto payload = ImGui::AcceptDragDropPayload(Metadata::EnumToString(IresObject::KD_Spritesheet).data())) {
auto spritesheet = *static_cast<IresSpritesheet* const*>(payload->Data);
ea->confSprite.Attach(spritesheet);
auto def = spritesheet->GetInstance();
@@ -929,7 +938,7 @@ void EditorInstance::ShowInspector(GameObject* object) {
ImGui::SameLine();
IresObject::ShowReferenceSafe(*this, ea->confMaterial.Get());
if (ImGui::BeginDragDropTarget()) {
- if (auto payload = ImGui::AcceptDragDropPayload(IresObject::ToString(IresObject::KD_Material).data())) {
+ if (auto payload = ImGui::AcceptDragDropPayload(Metadata::EnumToString(IresObject::KD_Material).data())) {
auto material = *static_cast<IresMaterial* const*>(payload->Data);
ea->confMaterial.Attach(material);
player->SetMaterial(material->GetInstance());
diff --git a/source/30-game/GameObject.cpp b/source/30-game/GameObject.cpp
index 8bb3ec7..3b15111 100644
--- a/source/30-game/GameObject.cpp
+++ b/source/30-game/GameObject.cpp
@@ -2,11 +2,14 @@
#include "Level.hpp"
#include "Player.hpp"
-#include "RapidJsonHelper.hpp"
#include "SceneThings.hpp"
#include "World.hpp"
+#include <Metadata.hpp>
+#include <RapidJsonHelper.hpp>
+
#include <rapidjson/document.h>
+#include <cassert>
#include <string_view>
#include <utility>
@@ -14,11 +17,12 @@ using namespace std::literals;
namespace ProjectBrussel_UNITY_ID {
GameObject* CreateGameObject(GameObject::Kind kind, GameWorld* world) {
+ using enum Tags::GameObjectKind;
switch (kind) {
- case GameObject::KD_Generic: return new GameObject(world);
- case GameObject::KD_SimpleGeometry: return new SimpleGeometryObject(world);
- case GameObject::KD_Building: return new BuildingObject(world);
- case GameObject::KD_LevelWrapper: return new LevelWrapperObject(world);
+ case KD_Generic: return new GameObject(world);
+ case KD_SimpleGeometry: return new SimpleGeometryObject(world);
+ case KD_Building: return new BuildingObject(world);
+ case KD_LevelWrapper: return new LevelWrapperObject(world);
default: break;
}
return nullptr;
@@ -60,27 +64,6 @@ GameObject::~GameObject() {
}
}
-std::string_view GameObject::ToString(Kind kind) {
- switch (kind) {
- case KD_Generic: return "GameObject"sv;
- case KD_Player: return "Player"sv;
- case KD_SimpleGeometry: return "SimpleGeometry"sv;
- case KD_Building: return "Building"sv;
- case KD_LevelWrapper: return "LevelWrapper"sv;
- case KD_COUNT: break;
- }
- return std::string_view();
-}
-
-GameObject::Kind GameObject::FromString(std::string_view name) {
- if (name == "GameObject"sv) return KD_Generic;
- if (name == "Player"sv) return KD_Player;
- if (name == "SimpleGeometry"sv) return KD_SimpleGeometry;
- if (name == "Building"sv) return KD_Building;
- if (name == "LevelWrapper"sv) return KD_LevelWrapper;
- return KD_COUNT;
-}
-
GameObject::Kind GameObject::GetKind() const {
return mKind;
}
@@ -204,7 +187,7 @@ void GameObject::Update() {
rapidjson::Value GameObject::Serialize(GameObject* obj, rapidjson::Document& root) {
rapidjson::Value result(rapidjson::kObjectType);
- result.AddMember("Type", rapidjson::StringRef(ToString(obj->GetKind())), root.GetAllocator());
+ result.AddMember("Type", rapidjson::StringRef(Metadata::EnumToString(obj->GetKind())), root.GetAllocator());
rapidjson::Value rvValue(rapidjson::kObjectType);
obj->WriteSaveFormat(rvValue, root);
@@ -222,8 +205,9 @@ std::unique_ptr<GameObject> GameObject::Deserialize(const rapidjson::Value& valu
auto rvValue = rapidjson::GetProperty(value, rapidjson::kObjectType, "Value"sv);
if (!rvValue) return nullptr;
- auto kind = FromString(rapidjson::AsStringView(*rvType));
- auto obj = std::unique_ptr<GameObject>(CreateGameObject(kind, world));
+ auto kind = Metadata::EnumFromString<Kind>(rapidjson::AsStringView(*rvType));
+ assert(kind.has_value());
+ auto obj = std::unique_ptr<GameObject>(CreateGameObject(kind.value(), world));
if (!obj) return nullptr;
obj->ReadSaveFormat(*rvValue);
@@ -242,3 +226,5 @@ void GameObject::SetParent(GameObject* parent) {
// needUpdate();
}
}
+
+#include <generated/GameObject.gs.inl>
diff --git a/source/30-game/GameObject.hpp b/source/30-game/GameObject.hpp
index 77488b9..f975803 100644
--- a/source/30-game/GameObject.hpp
+++ b/source/30-game/GameObject.hpp
@@ -2,27 +2,35 @@
#include "EditorAttachment.hpp"
#include "Material.hpp"
-#include "PodVector.hpp"
#include "Renderer.hpp"
#include "VertexIndex.hpp"
+#include <MacrosCodegen.hpp>
+#include <PodVector.hpp>
+
#include <rapidjson/fwd.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <span>
#include <vector>
+namespace Tags {
+enum class GameObjectKind {
+ KD_Generic,
+ KD_Player,
+ KD_SimpleGeometry,
+ KD_Building,
+ KD_LevelWrapper,
+ KD_COUNT,
+};
+BRUSSEL_ENUM(GameObjectKind, ToString FromString ExcludeHeuristics);
+} // namespace Tags
+
class GameWorld;
class GameObject {
public:
- enum Kind {
- KD_Generic,
- KD_Player,
- KD_SimpleGeometry,
- KD_Building,
- KD_LevelWrapper,
- KD_COUNT,
- };
+ using Kind = Tags::GameObjectKind;
+ using enum Tags::GameObjectKind;
private:
std::unique_ptr<EditorAttachment> mEditorAttachment;
@@ -50,8 +58,6 @@ public:
GameObject(GameObject&&) = default;
GameObject& operator=(GameObject&&) = default;
- static std::string_view ToString(Kind kind);
- static Kind FromString(std::string_view name);
Kind GetKind() const;
GameWorld* GetWorld() const;
@@ -92,3 +98,5 @@ public:
protected:
void SetParent(GameObject* parent);
};
+
+#include <generated/GameObject.gh.inl>
diff --git a/source/30-game/Ires.cpp b/source/30-game/Ires.cpp
index 10a6867..bfa4cdf 100644
--- a/source/30-game/Ires.cpp
+++ b/source/30-game/Ires.cpp
@@ -3,14 +3,16 @@
#include "AppConfig.hpp"
#include "EditorCore.hpp"
#include "EditorUtils.hpp"
-#include "Macros.hpp"
#include "Material.hpp"
-#include "RapidJsonHelper.hpp"
-#include "ScopeGuard.hpp"
#include "Shader.hpp"
#include "Sprite.hpp"
#include "Texture.hpp"
-#include "Utils.hpp"
+
+#include <Macros.hpp>
+#include <Metadata.hpp>
+#include <RapidJsonHelper.hpp>
+#include <ScopeGuard.hpp>
+#include <Utils.hpp>
#include <imgui.h>
#include <misc/cpp/imgui_stdlib.h>
@@ -29,27 +31,6 @@ IresObject::IresObject(Kind kind)
: mKind{ 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;
- case KD_COUNT: break;
- }
- return std::string_view();
-}
-
-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;
- return KD_COUNT;
-}
-
std::unique_ptr<IresObject> IresObject::Create(Kind kind) {
switch (kind) {
case KD_Texture: return std::make_unique<IresTexture>();
@@ -128,7 +109,7 @@ void IresObject::ShowReference(IEditor& editor) {
}
void IresObject::ShowEditor(IEditor& editor) {
- ImGui::Text("%s", ToString(mKind).data());
+ ImGui::Text("%.*s", PRINTF_STRING_VIEW(Metadata::EnumToString(mKind)));
bool isAnnoymous = mName.empty();
if (isAnnoymous) {
@@ -148,7 +129,7 @@ void IresObject::WriteFull(IresWritingContext& ctx, IresObject* ires, rapidjson:
rapidjson::Value rvIres(rapidjson::kObjectType);
ires->Write(ctx, rvIres, root);
- value.AddMember("Type", rapidjson::StringRef(ToString(ires->GetKind())), root.GetAllocator());
+ value.AddMember("Type", rapidjson::StringRef(Metadata::EnumToString(ires->GetKind())), root.GetAllocator());
value.AddMember("Uid", ires->mUid.Write(root), root.GetAllocator());
value.AddMember("Value", rvIres, root.GetAllocator());
}
@@ -169,8 +150,9 @@ std::unique_ptr<IresObject> IresObject::ReadFull(IresLoadingContext& ctx, const
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));
- auto ires = Create(kind);
+ auto kind = Metadata::EnumFromString<Kind>(rapidjson::AsStringView(*rvType));
+ assert(kind.has_value());
+ auto ires = Create(kind.value());
if (!ires) return nullptr;
auto rvUid = rapidjson::GetProperty(value, rapidjson::kArrayType, "Uid"sv);
@@ -212,7 +194,7 @@ void IresManager::DiscoverFiles(const fs::path& dir) {
std::vector<std::vector<LoadCandidate*>> candidatesByKind;
IresLoadTimeContext() {
- candidatesByKind.resize(IresObject::KD_COUNT);
+ candidatesByKind.resize((int)IresObject::KD_COUNT);
}
std::vector<LoadCandidate*>& GetByKind(IresObject::Kind kind) {
@@ -282,7 +264,7 @@ void IresManager::DiscoverFiles(const fs::path& dir) {
// 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) {
+ for (int i = 0; i < (int)IresObject::KD_COUNT; ++i) {
auto kind = static_cast<IresObject::Kind>(i);
auto& list = ctx.GetByKind(kind);
for (auto cand : list) {
@@ -302,7 +284,7 @@ void IresManager::DiscoverFiles(const fs::path& dir) {
std::pair<IresObject*, bool> IresManager::Add(IresObject* ires) {
auto& name = ires->mName;
if (name.empty()) {
- name = Utils::MakeRandomNumberedName(IresObject::ToString(ires->GetKind()).data());
+ name = Utils::MakeRandomNumberedName(Metadata::EnumToString(ires->GetKind()).data());
}
auto& uid = ires->mUid;
@@ -423,3 +405,5 @@ IresObject* IresManager::FindIres(const Uid& uid) const {
return nullptr;
}
}
+
+#include <generated/Ires.gs.inl>
diff --git a/source/30-game/Ires.hpp b/source/30-game/Ires.hpp
index 83ca175..b6420f3 100644
--- a/source/30-game/Ires.hpp
+++ b/source/30-game/Ires.hpp
@@ -2,9 +2,11 @@
#include "EditorAttachment.hpp"
#include "EditorCore.hpp"
-#include "RcPtr.hpp"
-#include "Uid.hpp"
-#include "Utils.hpp"
+
+#include <MacrosCodegen.hpp>
+#include <RcPtr.hpp>
+#include <Uid.hpp>
+#include <Utils.hpp>
#include <rapidjson/fwd.h>
#include <robin_hood.h>
@@ -17,18 +19,24 @@ class IresManager;
class IresWritingContext;
class IresLoadingContext;
+namespace Tags {
+enum class IresObjectKind {
+ KD_Texture,
+ KD_Shader,
+ KD_Material,
+ KD_SpriteFiles,
+ KD_Spritesheet,
+ KD_COUNT,
+};
+BRUSSEL_ENUM(IresObjectKind, ToString FromString ExcludeHeuristics);
+} // namespace Tags
+
class IresObject : public RefCounted {
friend class IresManager;
public:
- enum Kind {
- KD_Texture,
- KD_Shader,
- KD_Material,
- KD_SpriteFiles,
- KD_Spritesheet,
- KD_COUNT,
- };
+ using Kind = Tags::IresObjectKind;
+ using enum Tags::IresObjectKind;
private:
std::string mName; // Serialized as filename
@@ -41,8 +49,6 @@ public:
IresObject(Kind kind);
virtual ~IresObject() = default;
- static std::string_view ToString(Kind kind);
- static Kind FromString(std::string_view name);
static std::unique_ptr<IresObject> Create(Kind kind);
Kind GetKind() const { return mKind; }
@@ -115,3 +121,5 @@ public:
const auto& GetObjects() const { return mObjByUid; }
virtual IresObject* FindIres(const Uid& uid) const override;
};
+
+#include <generated/Ires.gh.inl>
diff --git a/source/30-game/Level.cpp b/source/30-game/Level.cpp
index 5881084..076e5d5 100644
--- a/source/30-game/Level.cpp
+++ b/source/30-game/Level.cpp
@@ -1,21 +1,24 @@
#include "Level.hpp"
#include "AppConfig.hpp"
-#include "PodVector.hpp"
-#include "RapidJsonHelper.hpp"
-#include "ScopeGuard.hpp"
-#include "Utils.hpp"
+#include <PodVector.hpp>
+#include <RapidJsonHelper.hpp>
+#include <ScopeGuard.hpp>
+#include <Utils.hpp>
+
+#include <imgui.h>
#include <rapidjson/document.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/filewritestream.h>
-#include <rapidjson/writer.h>
+#include <rapidjson/prettywriter.h>
#include <cstdio>
#include <filesystem>
using namespace std::literals;
namespace fs = std::filesystem;
+constexpr auto kParentToRootObject = std::numeric_limits<size_t>::max();
constexpr auto kInvalidEntryId = std::numeric_limits<size_t>::max();
struct Level::InstanciationEntry {
@@ -29,6 +32,23 @@ Level::Level() = default;
Level::~Level() = default;
void Level::Instanciate(GameObject* relRoot) const {
+ auto objectsLut = std::make_unique<GameObject*[]>(mEntries.size());
+ for (auto& entry : mEntries) {
+ GameObject* parent;
+ if (entry.parentId == kParentToRootObject) {
+ parent = relRoot;
+ } else {
+ parent = objectsLut[entry.parentId];
+ }
+
+ // TODO deser object
+ }
+}
+
+void Level::ShowInstanciationEntries(IEditor& editor) {
+ for (auto& entry : mEntries) {
+ // TODO
+ }
}
void LevelManager::DiscoverFilesDesignatedLocation() {
@@ -92,6 +112,7 @@ Level* LevelManager::LoadLevel(const Uid& uid) {
ldObj.level.Attach(level = new Level());
level->mMan = this;
+ level->mUid = uid;
#if defined(BRUSSEL_DEV_ENV)
BRUSSEL_JSON_GET_DEFAULT(root, "Name", std::string, ldObj.name, BRUSSEL_DEF_LEVEL_NAME);
@@ -123,8 +144,9 @@ void LevelManager::PrepareLevel(const Uid& uid) {
}
LevelManager::LoadableObject& LevelManager::AddLevel(const Uid& uid) {
- auto&& [iter, inserted] = mObjByUid.try_emplace(uid, LoadableObject{});
+ auto&& [iter, inserted] = mObjByUid.try_emplace(uid);
auto& ldObj = iter->second;
+ ldObj.level->mUid = uid;
#if defined(BRUSSEL_DEV_ENV)
ldObj.name = BRUSSEL_DEF_LEVEL_NAME;
ldObj.description = BRUSSEL_DEF_LEVEL_DESC;
@@ -132,6 +154,37 @@ LevelManager::LoadableObject& LevelManager::AddLevel(const Uid& uid) {
return ldObj;
}
+void LevelManager::SaveLevel(const Uid& uid) const {
+ auto iter = mObjByUid.find(uid);
+ if (iter == mObjByUid.end()) return;
+ auto& obj = iter->second;
+
+ SaveLevelImpl(obj, obj.filePath);
+}
+
+void LevelManager::SaveLevel(const Uid& uid, const std::filesystem::path& path) const {
+ auto iter = mObjByUid.find(uid);
+ if (iter == mObjByUid.end()) return;
+ auto& obj = iter->second;
+
+ SaveLevelImpl(obj, path);
+}
+
+void LevelManager::SaveLevelImpl(const LoadableObject& obj, const std::filesystem::path& path) const {
+ rapidjson::Document root;
+
+ // TODO
+
+ auto file = Utils::OpenCstdioFile(path, Utils::WriteTruncate);
+ if (!file) return;
+ DEFER { fclose(file); };
+
+ char writerBuffer[65536];
+ rapidjson::FileWriteStream stream(file, writerBuffer, sizeof(writerBuffer));
+ rapidjson::Writer<rapidjson::FileWriteStream> writer(stream);
+ root.Accept(writer);
+}
+
LevelWrapperObject::LevelWrapperObject(GameWorld* world)
: GameObject(KD_LevelWrapper, world) //
{
diff --git a/source/30-game/Level.hpp b/source/30-game/Level.hpp
index c1170a3..9114a64 100644
--- a/source/30-game/Level.hpp
+++ b/source/30-game/Level.hpp
@@ -1,8 +1,10 @@
#pragma once
+#include "EditorCore.hpp"
#include "GameObject.hpp"
-#include "RcPtr.hpp"
-#include "Uid.hpp"
+
+#include <RcPtr.hpp>
+#include <Uid.hpp>
#include <robin_hood.h>
#include <filesystem>
@@ -20,6 +22,7 @@ private:
struct InstanciationEntry;
LevelManager* mMan;
+ Uid mUid;
std::vector<InstanciationEntry> mEntries;
public:
@@ -27,6 +30,12 @@ public:
~Level();
void Instanciate(GameObject* relRoot) const;
+
+ LevelManager* GetLinkedLevelManager() const { return mMan; }
+ const Uid& GetUid() const { return mUid; }
+
+ // Editor stuff
+ void ShowInstanciationEntries(IEditor& editor);
};
class LevelManager {
@@ -34,12 +43,16 @@ public:
static inline LevelManager* instance = nullptr;
public: // NOTE: public for the editor; actual game components should not modify the map using this
+ // TODO maybe cut this struct to only the first RcPtr<Level> field in release mode?
struct LoadableObject {
RcPtr<Level> level; // TODO make weak pointer
std::filesystem::path filePath;
// NOTE: these fields are only loaded in dev mode
std::string name;
std::string description;
+
+ // Editor book keeping fields
+ bool edited = false;
};
// We want pointer stability here for the editor (inspector object)
robin_hood::unordered_node_map<Uid, LoadableObject> mObjByUid;
@@ -54,8 +67,16 @@ public:
/// Send the given level to be loaded on another thread
void PrepareLevel(const Uid& uid);
- // These should only be used by the editor
+ /// Create and add a new level object with the given uid.
+ /// Should only be used by the editor.
LoadableObject& AddLevel(const Uid& uid);
+ /// Should only be used by the editor.
+ void SaveLevel(const Uid& uid) const;
+ /// Should only be used by the editor.
+ void SaveLevel(const Uid& uid, const std::filesystem::path& path) const;
+
+private:
+ void SaveLevelImpl(const LoadableObject& obj, const std::filesystem::path& path) const;
};
class LevelWrapperObject : public GameObject {
diff --git a/source/30-game/Material.cpp b/source/30-game/Material.cpp
index e648970..9b0c42d 100644
--- a/source/30-game/Material.cpp
+++ b/source/30-game/Material.cpp
@@ -3,9 +3,11 @@
#include "AppConfig.hpp"
#include "EditorCore.hpp"
#include "EditorUtils.hpp"
-#include "RapidJsonHelper.hpp"
-#include "ScopeGuard.hpp"
-#include "Utils.hpp"
+
+#include <Metadata.hpp>
+#include <RapidJsonHelper.hpp>
+#include <ScopeGuard.hpp>
+#include <Utils.hpp>
#include <imgui.h>
#include <rapidjson/document.h>
@@ -349,7 +351,7 @@ void IresMaterial::ShowEditor(IEditor& editor) {
IresObject::ShowReferenceNull(editor);
}
if (ImGui::BeginDragDropTarget()) {
- if (auto payload = ImGui::AcceptDragDropPayload(ToString(KD_Shader).data())) {
+ if (auto payload = ImGui::AcceptDragDropPayload(Metadata::EnumToString(KD_Shader).data())) {
auto shader = *static_cast<IresShader* const*>(payload->Data);
mInstance->SetShader(shader->GetInstance());
}