From c1003e545d5b35fbf0cd9875f5cc18860a0e61b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Wed, 20 May 2026 15:02:45 +0200 Subject: [PATCH 01/34] Base Data Container asset class --- Engine_Master_UPC/AssetType.h | 3 +- Engine_Master_UPC/DataContainer.cpp | 149 ++++++++++++++++++++ Engine_Master_UPC/DataContainer.h | 29 ++++ Engine_Master_UPC/Engine.vcxproj | 4 + Engine_Master_UPC/Extensions.h | 1 + Engine_Master_UPC/ImporterDataContainer.cpp | 95 +++++++++++++ Engine_Master_UPC/ImporterDataContainer.h | 26 ++++ Engine_Master_UPC/ModuleAssets.cpp | 2 + Engine_Master_UPC/ModuleAssets.h | 2 + 9 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 Engine_Master_UPC/DataContainer.cpp create mode 100644 Engine_Master_UPC/DataContainer.h create mode 100644 Engine_Master_UPC/ImporterDataContainer.cpp create mode 100644 Engine_Master_UPC/ImporterDataContainer.h diff --git a/Engine_Master_UPC/AssetType.h b/Engine_Master_UPC/AssetType.h index d546cfa2..1a77ed16 100644 --- a/Engine_Master_UPC/AssetType.h +++ b/Engine_Master_UPC/AssetType.h @@ -13,6 +13,7 @@ enum class AssetType : uint32_t SKIN = 7, ANIMATION_STATE_MACHINE = 8, SCENE = 9, + DATA_CONTAINER = 10, - UNKNOWN = 10 + UNKNOWN = 11 }; \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainer.cpp b/Engine_Master_UPC/DataContainer.cpp new file mode 100644 index 00000000..d11a9e6a --- /dev/null +++ b/Engine_Master_UPC/DataContainer.cpp @@ -0,0 +1,149 @@ +#include "Globals.h" +#include "DataContainer.h" + +#include + +rapidjson::Value DataContainer::getJson(rapidjson::Document::AllocatorType& allocator) const +{ + return rapidjson::Value(m_data, allocator); +} + +bool DataContainer::deserializeJson(const rapidjson::Value& obj) +{ + if (!obj.IsObject()) + { + return false; + } + + m_data.CopyFrom(obj, m_data.GetAllocator()); + return true; +} + +void DataContainer::drawUI() +{ + ImGui::Text("Data Container"); + ImGui::Separator(); + + ImGui::TextDisabled("UID: %llu", static_cast(getUID())); + + ImGui::Spacing(); + ImGui::SeparatorText("Properties"); + + if (m_data.IsObject() && m_data.MemberCount() == 0) + { + ImGui::TextDisabled("No properties defined."); + ImGui::Spacing(); + ImGui::TextWrapped("Override getJson()/deserializeJson() in a subclass to add typed properties,"); + ImGui::TextWrapped("or add entries directly in the .datacontainer JSON file."); + return; + } + + if (!m_data.IsObject()) + { + ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Invalid data document."); + return; + } + + for (auto it = m_data.MemberBegin(); it != m_data.MemberEnd(); ++it) + { + const char* key = it->name.GetString(); + rapidjson::Value& value = it->value; + + ImGui::PushID(key); + + if (value.IsString()) + { + std::string buffer = value.GetString(); + buffer.resize(256, '\0'); + if (ImGui::InputText(key, &buffer[0], buffer.size())) + { + value.SetString(buffer.c_str(), m_data.GetAllocator()); + } + } + else if (value.IsInt()) + { + int v = value.GetInt(); + if (ImGui::InputInt(key, &v)) + { + value.SetInt(v); + } + } + else if (value.IsInt64()) + { + int v = static_cast(value.GetInt64()); + if (ImGui::InputInt(key, &v)) + { + value.SetInt64(v); + } + } + else if (value.IsUint64()) + { + int v = static_cast(value.GetUint64()); + if (ImGui::InputInt(key, &v)) + { + value.SetUint64(static_cast(v)); + } + } + else if (value.IsFloat() || value.IsDouble()) + { + float v = value.GetFloat(); + if (ImGui::DragFloat(key, &v, 0.1f)) + { + value.SetFloat(v); + } + } + else if (value.IsBool()) + { + bool v = value.GetBool(); + if (ImGui::Checkbox(key, &v)) + { + value.SetBool(v); + } + } + else if (value.IsArray()) + { + if (ImGui::TreeNode(key, "%s [%u items]", key, value.Size())) + { + for (rapidjson::SizeType i = 0; i < value.Size(); ++i) + { + ImGui::PushID(static_cast(i)); + rapidjson::Value& elem = value[i]; + + if (elem.IsString()) + { + ImGui::Text("[%u]: %s", i, elem.GetString()); + } + else if (elem.IsNumber()) + { + if (elem.IsInt()) + ImGui::Text("[%u]: %d", i, elem.GetInt()); + else + ImGui::Text("[%u]: %.3f", i, elem.GetFloat()); + } + else if (elem.IsBool()) + { + ImGui::Text("[%u]: %s", i, elem.GetBool() ? "true" : "false"); + } + else if (elem.IsObject()) + { + ImGui::Text("[%u]: { ... }", i); + } + + ImGui::PopID(); + } + + ImGui::TreePop(); + } + } + else if (value.IsObject()) + { + ImGui::Text("%s: { ... }", key); + } + else + { + ImGui::TextDisabled("%s: (unsupported type)", key); + } + + ImGui::PopID(); + } +} diff --git a/Engine_Master_UPC/DataContainer.h b/Engine_Master_UPC/DataContainer.h new file mode 100644 index 00000000..def6f819 --- /dev/null +++ b/Engine_Master_UPC/DataContainer.h @@ -0,0 +1,29 @@ +#pragma once +#include "Asset.h" + +#include + +class ImporterDataContainer; + +class DataContainer : public Asset +{ +public: + friend class ImporterDataContainer; + + DataContainer() = default; + explicit DataContainer(AssetReference& id) + : Asset(id, AssetType::DATA_CONTAINER) + { + m_data.SetObject(); + } + + virtual rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const; + virtual bool deserializeJson(const rapidjson::Value& obj); + void drawUI() override; + + const rapidjson::Document& getData() const { return m_data; } + rapidjson::Document& getDataMutable() { return m_data; } + +protected: + rapidjson::Document m_data; +}; diff --git a/Engine_Master_UPC/Engine.vcxproj b/Engine_Master_UPC/Engine.vcxproj index cf7e015c..a2ab7034 100644 --- a/Engine_Master_UPC/Engine.vcxproj +++ b/Engine_Master_UPC/Engine.vcxproj @@ -302,6 +302,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + @@ -324,6 +325,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + @@ -655,8 +657,10 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + + diff --git a/Engine_Master_UPC/Extensions.h b/Engine_Master_UPC/Extensions.h index d4966423..ce474158 100644 --- a/Engine_Master_UPC/Extensions.h +++ b/Engine_Master_UPC/Extensions.h @@ -6,6 +6,7 @@ constexpr const char* MATERIAL_EXTENSION = ".material"; constexpr const char* ANIMATION_EXTENSION = ".anim"; constexpr const char* ANIMATION_STATE_MACHINE_EXTENSION = ".statemachine"; constexpr const char* SCENE_EXTENSION = ".scene"; +constexpr const char* DATA_CONTAINER_EXTENSION = ".datacontainer"; constexpr const char* PNG_EXTENSION = ".png"; constexpr const char* JPG_EXTENSION = ".jpg"; diff --git a/Engine_Master_UPC/ImporterDataContainer.cpp b/Engine_Master_UPC/ImporterDataContainer.cpp new file mode 100644 index 00000000..29dbf83f --- /dev/null +++ b/Engine_Master_UPC/ImporterDataContainer.cpp @@ -0,0 +1,95 @@ +#include "Globals.h" +#include "ImporterDataContainer.h" + +#include "BinaryReader.h" +#include "BinaryWriter.h" + +#include +#include +#include +#include "rapidjson/filereadstream.h" + +#include +#include + +bool ImporterDataContainer::saveNative(const DataContainer* asset, const std::filesystem::path& path) +{ + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + asset->m_data.Accept(writer); + + std::ofstream file(path); + if (!file.is_open()) + { + DEBUG_ERROR("[ImporterDataContainer] Could not open '%s' for writing.", path.string().c_str()); + return false; + } + + file << buffer.GetString(); + return file.good(); +} + +bool ImporterDataContainer::importNative(const std::filesystem::path& path, DataContainer* dst) +{ + if (!dst) + { + return false; + } + + FILE* fp = std::fopen(path.string().c_str(), "rb"); + if (!fp) + { + DEBUG_ERROR("[ImporterDataContainer] Could not open '%s'.", path.string().c_str()); + return false; + } + + char readBuffer[65536]; + rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + + rapidjson::Document doc; + doc.ParseStream(is); + std::fclose(fp); + + if (doc.HasParseError() || !doc.IsObject()) + { + DEBUG_ERROR("[ImporterDataContainer] JSON parse error in '%s'.", path.string().c_str()); + return false; + } + + return dst->deserializeJson(doc); +} + +uint64_t ImporterDataContainer::saveTyped(const DataContainer* source, uint8_t** outBuffer) +{ + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + source->m_data.Accept(writer); + + const std::string jsonStr = buffer.GetString(); + const uint64_t size = sizeof(uint32_t) + sizeof(uint32_t) + jsonStr.size(); + + uint8_t* data = new uint8_t[size]; + BinaryWriter bw(data); + + bw.u32(1); + bw.string(jsonStr); + + *outBuffer = data; + return size; +} + +void ImporterDataContainer::loadTyped(const uint8_t* buffer, DataContainer* dst) +{ + BinaryReader reader(buffer); + + const uint32_t version = reader.u32(); + const std::string jsonStr = reader.string(); + + rapidjson::Document doc; + doc.Parse(jsonStr.c_str()); + + if (!doc.HasParseError() && doc.IsObject()) + { + dst->deserializeJson(doc); + } +} diff --git a/Engine_Master_UPC/ImporterDataContainer.h b/Engine_Master_UPC/ImporterDataContainer.h new file mode 100644 index 00000000..47568094 --- /dev/null +++ b/Engine_Master_UPC/ImporterDataContainer.h @@ -0,0 +1,26 @@ +#pragma once +#include "ImporterNative.h" +#include "DataContainer.h" +#include "Extensions.h" + +class ImporterDataContainer + : public ImporterNative +{ +public: + bool canImport(const std::filesystem::path& path) const override + { + return path.extension().string() == DATA_CONTAINER_EXTENSION; + } + + Asset* createAssetInstance(AssetReference& uid) const override + { + return new DataContainer(uid); + } + + bool saveNative(const DataContainer* asset, const std::filesystem::path& path); + +protected: + bool importNative(const std::filesystem::path& path, DataContainer* dst) override; + uint64_t saveTyped(const DataContainer* source, uint8_t** outBuffer) override; + void loadTyped(const uint8_t* buffer, DataContainer* dst) override; +}; diff --git a/Engine_Master_UPC/ModuleAssets.cpp b/Engine_Master_UPC/ModuleAssets.cpp index 9adc73cc..44da59da 100644 --- a/Engine_Master_UPC/ModuleAssets.cpp +++ b/Engine_Master_UPC/ModuleAssets.cpp @@ -14,6 +14,7 @@ #include "ImporterGltf.h" #include "ImporterFont.h" #include "ImporterScene.h" +#include "ImporterDataContainer.h" #include "MD5.h" #include "AssetScanner.h" @@ -73,6 +74,7 @@ bool ModuleAssets::init() m_importerAnimation, m_importerSkin, m_importerAnimationStateMachine)); m_importers.push_back(m_importerFont = new ImporterFont()); m_importers.push_back(m_importerScene = new ImporterScene()); + m_importers.push_back(m_importerDataContainer = new ImporterDataContainer()); m_scanner = std::make_unique(); m_contentRegistry = std::make_unique(this); diff --git a/Engine_Master_UPC/ModuleAssets.h b/Engine_Master_UPC/ModuleAssets.h index 46a4a931..0d886bfc 100644 --- a/Engine_Master_UPC/ModuleAssets.h +++ b/Engine_Master_UPC/ModuleAssets.h @@ -33,6 +33,7 @@ class ImporterAnimationStateMachine; class ImporterGltf; class ImporterFont; class ImporterScene; +class ImporterDataContainer; struct ScanFileResult; @@ -238,6 +239,7 @@ friend PrefabManager; ImporterFont* m_importerFont = nullptr; ImporterScene* m_importerScene = nullptr; ImporterAnimationStateMachine* m_importerAnimationStateMachine = nullptr; + ImporterDataContainer* m_importerDataContainer = nullptr; std::vector m_importers; #pragma endregion From 7933ff141ee6de9b10de74032cfc74e06923c486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Wed, 20 May 2026 19:40:15 +0200 Subject: [PATCH 02/34] Created DataContainer System similar to the Script one --- .../CommandCreateDataContainer.cpp | 58 +++++++++++++++++++ .../CommandCreateDataContainer.h | 19 ++++++ Engine_Master_UPC/DataContainer.h | 4 ++ Engine_Master_UPC/DataContainerAPI.h | 27 +++++++++ Engine_Master_UPC/DataContainerAutoRegister.h | 28 +++++++++ Engine_Master_UPC/DataContainerCreator.h | 8 +++ Engine_Master_UPC/DataContainerFactory.cpp | 50 ++++++++++++++++ Engine_Master_UPC/DataContainerFactory.h | 18 ++++++ Engine_Master_UPC/DataContainerRegistry.h | 12 ++++ Engine_Master_UPC/Engine.vcxproj | 8 +++ Engine_Master_UPC/EngineAPI.cpp | 6 ++ Engine_Master_UPC/EngineAPI.h | 2 + Engine_Master_UPC/ImporterDataContainer.cpp | 25 ++++++++ Engine_Master_UPC/ImporterDataContainer.h | 11 +--- Engine_Master_UPC/ModuleAssets.cpp | 1 + Engine_Master_UPC/ModuleAssets.h | 1 + Engine_Master_UPC/WindowFileDialog.cpp | 21 +++++++ 17 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 Engine_Master_UPC/CommandCreateDataContainer.cpp create mode 100644 Engine_Master_UPC/CommandCreateDataContainer.h create mode 100644 Engine_Master_UPC/DataContainerAPI.h create mode 100644 Engine_Master_UPC/DataContainerAutoRegister.h create mode 100644 Engine_Master_UPC/DataContainerCreator.h create mode 100644 Engine_Master_UPC/DataContainerFactory.cpp create mode 100644 Engine_Master_UPC/DataContainerFactory.h create mode 100644 Engine_Master_UPC/DataContainerRegistry.h diff --git a/Engine_Master_UPC/CommandCreateDataContainer.cpp b/Engine_Master_UPC/CommandCreateDataContainer.cpp new file mode 100644 index 00000000..6e118034 --- /dev/null +++ b/Engine_Master_UPC/CommandCreateDataContainer.cpp @@ -0,0 +1,58 @@ +#include "Globals.h" +#include "CommandCreateDataContainer.h" + +#include "Application.h" +#include "ModuleAssets.h" +#include "DataContainerFactory.h" +#include "UID.h" + +#include +#include +#include + +#include + +CommandCreateDataContainer::CommandCreateDataContainer( + const std::filesystem::path& targetDir, + const std::string& typeName, + const std::string& assetName, + const std::string& extension) + : m_targetDir(targetDir) + , m_typeName(typeName) + , m_assetName(assetName) + , m_extension(extension) +{ +} + +void CommandCreateDataContainer::run() +{ + std::filesystem::path filePath = m_targetDir / (m_assetName + m_extension); + + if (std::filesystem::exists(filePath)) + { + DEBUG_WARN("[CommandCreateDataContainer] File '%s' already exists.", filePath.string().c_str()); + return; + } + + rapidjson::Document doc; + doc.SetObject(); + rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); + + doc.AddMember("_typeName", rapidjson::Value(m_typeName.c_str(), allocator), allocator); + + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + doc.Accept(writer); + + std::ofstream file(filePath); + if (!file.is_open()) + { + DEBUG_ERROR("[CommandCreateDataContainer] Could not create '%s'.", filePath.string().c_str()); + return; + } + + file << buffer.GetString(); + file.close(); + + app->getModuleAssets()->refresh(); +} diff --git a/Engine_Master_UPC/CommandCreateDataContainer.h b/Engine_Master_UPC/CommandCreateDataContainer.h new file mode 100644 index 00000000..ea9ab3f0 --- /dev/null +++ b/Engine_Master_UPC/CommandCreateDataContainer.h @@ -0,0 +1,19 @@ +#pragma once +#include "ICommand.h" + +#include +#include + +class CommandCreateDataContainer : public ICommand +{ +public: + CommandCreateDataContainer(const std::filesystem::path& targetDir, const std::string& typeName, const std::string& assetName, const std::string& extension); + + void run() override; + +private: + std::filesystem::path m_targetDir; + std::string m_typeName; + std::string m_assetName; + std::string m_extension; +}; diff --git a/Engine_Master_UPC/DataContainer.h b/Engine_Master_UPC/DataContainer.h index def6f819..0e1fdb25 100644 --- a/Engine_Master_UPC/DataContainer.h +++ b/Engine_Master_UPC/DataContainer.h @@ -24,6 +24,10 @@ class DataContainer : public Asset const rapidjson::Document& getData() const { return m_data; } rapidjson::Document& getDataMutable() { return m_data; } + virtual const char* getTypeName() const { return "DataContainer"; } + virtual const char* getDisplayTypeName() const { return "Data Container"; } + virtual const char* getFileExtension() const { return ".datacontainer"; } + protected: rapidjson::Document m_data; }; diff --git a/Engine_Master_UPC/DataContainerAPI.h b/Engine_Master_UPC/DataContainerAPI.h new file mode 100644 index 00000000..5579224a --- /dev/null +++ b/Engine_Master_UPC/DataContainerAPI.h @@ -0,0 +1,27 @@ +#pragma once + +// Include this header in your external project to create custom DataContainer assets +// (similar to Unity ScriptableObjects) + +#include "DataContainer.h" +#include "DataContainerAutoRegister.h" +#include "EngineAPI.h" + +// Usage example: +// +// In your .h file: +// class MyConfig : public DataContainer { +// public: +// DECLARE_DATACONTAINER(MyConfig) +// MyConfig() = default; +// explicit MyConfig(AssetReference& id) : DataContainer(id) {} +// const char* getTypeName() const override { return "MyConfig"; } +// const char* getDisplayTypeName() const override { return "My Config"; } +// const char* getFileExtension() const override { return ".myconfig"; } +// // Add your typed accessor methods here... +// }; +// +// In your .cpp file: +// IMPLEMENT_DATACONTAINER(MyConfig, ".myconfig") +// +// The class will auto-register and appear in the FileDialog right-click "Create" menu. diff --git a/Engine_Master_UPC/DataContainerAutoRegister.h b/Engine_Master_UPC/DataContainerAutoRegister.h new file mode 100644 index 00000000..55c163bd --- /dev/null +++ b/Engine_Master_UPC/DataContainerAutoRegister.h @@ -0,0 +1,28 @@ +#pragma once + +#include "EngineAPI.h" + +class DataContainerAutoRegister +{ +public: + DataContainerAutoRegister(const char* name, const char* displayName, const char* extension, DataContainerCreator creator) + { + registerDataContainer(name, displayName, extension, creator); + } +}; + +#define DECLARE_DATACONTAINER(TypeName) \ +public: \ + static DataContainer* Create(AssetReference& uid); + +#define IMPLEMENT_DATACONTAINER(TypeName, Extension) \ + DataContainer* TypeName::Create(AssetReference& uid) \ + { \ + return new TypeName(uid); \ + } \ + static DataContainerAutoRegister s_autoRegister_##TypeName( \ + #TypeName, \ + #TypeName, \ + Extension, \ + &TypeName::Create \ + ); diff --git a/Engine_Master_UPC/DataContainerCreator.h b/Engine_Master_UPC/DataContainerCreator.h new file mode 100644 index 00000000..6c89c8d2 --- /dev/null +++ b/Engine_Master_UPC/DataContainerCreator.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +class AssetReference; +class DataContainer; + +using DataContainerCreator = DataContainer* (*)(AssetReference& uid); diff --git a/Engine_Master_UPC/DataContainerFactory.cpp b/Engine_Master_UPC/DataContainerFactory.cpp new file mode 100644 index 00000000..a9860886 --- /dev/null +++ b/Engine_Master_UPC/DataContainerFactory.cpp @@ -0,0 +1,50 @@ +#include "Globals.h" +#include "DataContainerFactory.h" +#include "AssetReference.h" + +std::vector DataContainerFactory::m_registry; + +void DataContainerFactory::registerDataContainer(const std::string& name, const std::string& displayName, const std::string& extension, DataContainerCreator creator) +{ + for (DataContainerRegistry& entry : m_registry) + { + if (entry.name == name) + { + entry.creator = creator; + return; + } + } + + m_registry.push_back({ name, displayName, extension, creator }); +} + +DataContainer* DataContainerFactory::createDataContainer(const std::string& name, AssetReference& uid) +{ + for (const DataContainerRegistry& entry : m_registry) + { + if (entry.name == name) + { + return entry.creator(uid); + } + } + + return nullptr; +} + +bool DataContainerFactory::isDataContainerRegistered(const std::string& name) +{ + for (const DataContainerRegistry& entry : m_registry) + { + if (entry.name == name) + { + return true; + } + } + + return false; +} + +const std::vector& DataContainerFactory::getAllRegistered() +{ + return m_registry; +} diff --git a/Engine_Master_UPC/DataContainerFactory.h b/Engine_Master_UPC/DataContainerFactory.h new file mode 100644 index 00000000..c8f877ea --- /dev/null +++ b/Engine_Master_UPC/DataContainerFactory.h @@ -0,0 +1,18 @@ +#pragma once + +#include "DataContainerRegistry.h" +#include + +class AssetReference; + +class DataContainerFactory +{ +public: + static void registerDataContainer(const std::string& name, const std::string& displayName, const std::string& extension, DataContainerCreator creator); + static DataContainer* createDataContainer(const std::string& name, AssetReference& uid); + static bool isDataContainerRegistered(const std::string& name); + static const std::vector& getAllRegistered(); + +private: + static std::vector m_registry; +}; diff --git a/Engine_Master_UPC/DataContainerRegistry.h b/Engine_Master_UPC/DataContainerRegistry.h new file mode 100644 index 00000000..5d3ff158 --- /dev/null +++ b/Engine_Master_UPC/DataContainerRegistry.h @@ -0,0 +1,12 @@ +#pragma once + +#include "DataContainerCreator.h" +#include + +struct DataContainerRegistry +{ + std::string name; + std::string displayName; + std::string extension; + DataContainerCreator creator; +}; diff --git a/Engine_Master_UPC/Engine.vcxproj b/Engine_Master_UPC/Engine.vcxproj index a2ab7034..a84a8e98 100644 --- a/Engine_Master_UPC/Engine.vcxproj +++ b/Engine_Master_UPC/Engine.vcxproj @@ -301,8 +301,14 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + + + + + + @@ -647,9 +653,11 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + + diff --git a/Engine_Master_UPC/EngineAPI.cpp b/Engine_Master_UPC/EngineAPI.cpp index b6f9be60..f74406d3 100644 --- a/Engine_Master_UPC/EngineAPI.cpp +++ b/Engine_Master_UPC/EngineAPI.cpp @@ -14,6 +14,7 @@ #include "Scene.h" #include "Keyboard.h" #include "ScriptFactory.h" +#include "DataContainerFactory.h" #include "GameObject.h" #include "Transform.h" @@ -44,6 +45,11 @@ void registerScript(const char* scriptName, ScriptCreator creator) ScriptFactory::registerScript(scriptName, creator); } +void registerDataContainer(const char* name, const char* displayName, const char* extension, DataContainerCreator creator) +{ + DataContainerFactory::registerDataContainer(name, displayName, extension, creator); +} + namespace GameObjectAPI { Transform* getTransform(GameObject* gameObject) diff --git a/Engine_Master_UPC/EngineAPI.h b/Engine_Master_UPC/EngineAPI.h index b398e4b8..73036685 100644 --- a/Engine_Master_UPC/EngineAPI.h +++ b/Engine_Master_UPC/EngineAPI.h @@ -7,6 +7,7 @@ #endif #include "ScriptCreator.h" +#include "DataContainerCreator.h" #include "ComponentType.h" #include "Tag.h" #include "SimpleMath.h" @@ -27,6 +28,7 @@ class Transform2D; struct HapticEffectDefinition; ENGINE_API void registerScript(const char* scriptName, ScriptCreator creator); +ENGINE_API void registerDataContainer(const char* name, const char* displayName, const char* extension, DataContainerCreator creator); namespace GameObjectAPI { diff --git a/Engine_Master_UPC/ImporterDataContainer.cpp b/Engine_Master_UPC/ImporterDataContainer.cpp index 29dbf83f..12575891 100644 --- a/Engine_Master_UPC/ImporterDataContainer.cpp +++ b/Engine_Master_UPC/ImporterDataContainer.cpp @@ -12,6 +12,31 @@ #include #include +bool ImporterDataContainer::canImport(const std::filesystem::path& path) const +{ + const std::string ext = path.extension().string(); + if (ext == DATA_CONTAINER_EXTENSION) + { + return true; + } + + const auto& registry = DataContainerFactory::getAllRegistered(); + for (const auto& entry : registry) + { + if (ext == entry.extension) + { + return true; + } + } + + return false; +} + +Asset* ImporterDataContainer::createAssetInstance(AssetReference& uid) const +{ + return new DataContainer(uid); +} + bool ImporterDataContainer::saveNative(const DataContainer* asset, const std::filesystem::path& path) { rapidjson::StringBuffer buffer; diff --git a/Engine_Master_UPC/ImporterDataContainer.h b/Engine_Master_UPC/ImporterDataContainer.h index 47568094..65184fbd 100644 --- a/Engine_Master_UPC/ImporterDataContainer.h +++ b/Engine_Master_UPC/ImporterDataContainer.h @@ -1,21 +1,16 @@ #pragma once #include "ImporterNative.h" #include "DataContainer.h" +#include "DataContainerFactory.h" #include "Extensions.h" class ImporterDataContainer : public ImporterNative { public: - bool canImport(const std::filesystem::path& path) const override - { - return path.extension().string() == DATA_CONTAINER_EXTENSION; - } + bool canImport(const std::filesystem::path& path) const override; - Asset* createAssetInstance(AssetReference& uid) const override - { - return new DataContainer(uid); - } + Asset* createAssetInstance(AssetReference& uid) const override; bool saveNative(const DataContainer* asset, const std::filesystem::path& path); diff --git a/Engine_Master_UPC/ModuleAssets.cpp b/Engine_Master_UPC/ModuleAssets.cpp index 44da59da..aad2f1c8 100644 --- a/Engine_Master_UPC/ModuleAssets.cpp +++ b/Engine_Master_UPC/ModuleAssets.cpp @@ -15,6 +15,7 @@ #include "ImporterFont.h" #include "ImporterScene.h" #include "ImporterDataContainer.h" +#include "DataContainerFactory.h" #include "MD5.h" #include "AssetScanner.h" diff --git a/Engine_Master_UPC/ModuleAssets.h b/Engine_Master_UPC/ModuleAssets.h index 0d886bfc..91b4d9ce 100644 --- a/Engine_Master_UPC/ModuleAssets.h +++ b/Engine_Master_UPC/ModuleAssets.h @@ -14,6 +14,7 @@ #include #include "FileIO.h" #include "Importer.h" +#include class AssetScanner; diff --git a/Engine_Master_UPC/WindowFileDialog.cpp b/Engine_Master_UPC/WindowFileDialog.cpp index 88a3498c..24379454 100644 --- a/Engine_Master_UPC/WindowFileDialog.cpp +++ b/Engine_Master_UPC/WindowFileDialog.cpp @@ -19,6 +19,9 @@ #include "CommandImportAsset.h" #include "CommandPasteFile.h" #include "CommandSaveGameObjectAsPrefab.h" +#include "CommandCreateDataContainer.h" + +#include "DataContainerFactory.h" #include #include @@ -377,6 +380,24 @@ void WindowFileDialog::drawAssetGrid(DirectoryEntry* directory) CommandCreateFolder(m_currentDirectory).run(); } + const auto& dcRegistry = DataContainerFactory::getAllRegistered(); + if (!dcRegistry.empty()) + { + ImGui::Spacing(); + if (ImGui::BeginMenu("New Data Asset")) + { + for (const auto& entry : dcRegistry) + { + if (ImGui::MenuItem(entry.displayName.c_str())) + { + std::string assetName = entry.displayName + "_New"; + CommandCreateDataContainer(m_currentDirectory, entry.name, assetName, entry.extension).run(); + } + } + ImGui::EndMenu(); + } + } + ImGui::Spacing(); ImGui::Spacing(); ImGui::Text("General"); From bd013665854cb6ef79a076bcda25f7647540ec6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Wed, 20 May 2026 22:42:10 +0200 Subject: [PATCH 03/34] DataContainer detection and creation via Editor --- Engine_Master_UPC/Asset.h | 8 +++- Engine_Master_UPC/DataContainer.h | 7 +++- Engine_Master_UPC/DataContainerCreator.h | 2 +- Engine_Master_UPC/DataContainerFactory.h | 2 +- Engine_Master_UPC/Extensions.h | 1 + Engine_Master_UPC/ImporterDataContainer.cpp | 2 +- Engine_Master_UPC/MD5.h | 1 + Engine_Master_UPC/ModuleAssets.cpp | 38 ++++++++++++++++++ Engine_Master_UPC/ModuleAssets.h | 14 ++++++- Engine_Master_UPC/ModuleEditor.cpp | 32 ++++++++++++++- GameScripts/BoundConfig.cpp | 44 +++++++++++++++++++++ GameScripts/BoundConfig.h | 29 ++++++++++++++ GameScripts/GameScripts.vcxproj | 2 + 13 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 GameScripts/BoundConfig.cpp create mode 100644 GameScripts/BoundConfig.h diff --git a/Engine_Master_UPC/Asset.h b/Engine_Master_UPC/Asset.h index 3362ff38..4b42409a 100644 --- a/Engine_Master_UPC/Asset.h +++ b/Engine_Master_UPC/Asset.h @@ -3,8 +3,12 @@ #include "AssetReference.h" #include "AssetsDictionary.h" #include "AssetType.h" +#include "EngineAPI.h" -class Asset +#pragma warning(push) +#pragma warning(disable: 4251) + +class ENGINE_API Asset { public: Asset() = default; @@ -24,3 +28,5 @@ class Asset AssetReference m_reference; AssetType m_type = AssetType::UNKNOWN; }; + +#pragma warning(pop) diff --git a/Engine_Master_UPC/DataContainer.h b/Engine_Master_UPC/DataContainer.h index 0e1fdb25..111b6446 100644 --- a/Engine_Master_UPC/DataContainer.h +++ b/Engine_Master_UPC/DataContainer.h @@ -1,11 +1,14 @@ #pragma once #include "Asset.h" +#pragma warning(push) +#pragma warning(disable: 4251) + #include class ImporterDataContainer; -class DataContainer : public Asset +class ENGINE_API DataContainer : public Asset { public: friend class ImporterDataContainer; @@ -31,3 +34,5 @@ class DataContainer : public Asset protected: rapidjson::Document m_data; }; + +#pragma warning(pop) diff --git a/Engine_Master_UPC/DataContainerCreator.h b/Engine_Master_UPC/DataContainerCreator.h index 6c89c8d2..364c9c9a 100644 --- a/Engine_Master_UPC/DataContainerCreator.h +++ b/Engine_Master_UPC/DataContainerCreator.h @@ -2,7 +2,7 @@ #include -class AssetReference; +struct AssetReference; class DataContainer; using DataContainerCreator = DataContainer* (*)(AssetReference& uid); diff --git a/Engine_Master_UPC/DataContainerFactory.h b/Engine_Master_UPC/DataContainerFactory.h index c8f877ea..df303f71 100644 --- a/Engine_Master_UPC/DataContainerFactory.h +++ b/Engine_Master_UPC/DataContainerFactory.h @@ -3,7 +3,7 @@ #include "DataContainerRegistry.h" #include -class AssetReference; +struct AssetReference; class DataContainerFactory { diff --git a/Engine_Master_UPC/Extensions.h b/Engine_Master_UPC/Extensions.h index ce474158..f9c85969 100644 --- a/Engine_Master_UPC/Extensions.h +++ b/Engine_Master_UPC/Extensions.h @@ -7,6 +7,7 @@ constexpr const char* ANIMATION_EXTENSION = ".anim"; constexpr const char* ANIMATION_STATE_MACHINE_EXTENSION = ".statemachine"; constexpr const char* SCENE_EXTENSION = ".scene"; constexpr const char* DATA_CONTAINER_EXTENSION = ".datacontainer"; +constexpr const char* CONFIG_EXTENSION = ".config"; constexpr const char* PNG_EXTENSION = ".png"; constexpr const char* JPG_EXTENSION = ".jpg"; diff --git a/Engine_Master_UPC/ImporterDataContainer.cpp b/Engine_Master_UPC/ImporterDataContainer.cpp index 12575891..42d81f92 100644 --- a/Engine_Master_UPC/ImporterDataContainer.cpp +++ b/Engine_Master_UPC/ImporterDataContainer.cpp @@ -15,7 +15,7 @@ bool ImporterDataContainer::canImport(const std::filesystem::path& path) const { const std::string ext = path.extension().string(); - if (ext == DATA_CONTAINER_EXTENSION) + if (ext == DATA_CONTAINER_EXTENSION || ext == CONFIG_EXTENSION) { return true; } diff --git a/Engine_Master_UPC/MD5.h b/Engine_Master_UPC/MD5.h index e1ca3eb4..1ddf3186 100644 --- a/Engine_Master_UPC/MD5.h +++ b/Engine_Master_UPC/MD5.h @@ -1,4 +1,5 @@ #pragma once +#include "Globals.h" #include #include #include diff --git a/Engine_Master_UPC/ModuleAssets.cpp b/Engine_Master_UPC/ModuleAssets.cpp index aad2f1c8..8c5bba98 100644 --- a/Engine_Master_UPC/ModuleAssets.cpp +++ b/Engine_Master_UPC/ModuleAssets.cpp @@ -16,6 +16,7 @@ #include "ImporterScene.h" #include "ImporterDataContainer.h" #include "DataContainerFactory.h" +#include "DataContainer.h" #include "MD5.h" #include "AssetScanner.h" @@ -147,6 +148,16 @@ void ModuleAssets::importAsset(const std::filesystem::path& sourcePath, AssetRef return; } + if (reference.m_type == AssetType::DATA_CONTAINER) + { + DataContainer* dc = resolveDataContainerType(static_cast(asset.get())); + if (dc != static_cast(asset.get())) + { + asset.release(); + asset.reset(dc); + } + } + if (!persistAsset(asset.get(), importer, reference, sourcePath)) { if (!isReimport) reference = AssetReference(); @@ -592,3 +603,30 @@ PrefabManager* ModuleAssets::getPrefabManager() const { return m_prefabManager.get(); } + +DataContainer* ModuleAssets::resolveDataContainerType(DataContainer* baseContainer) const +{ + if (!baseContainer) + { + return nullptr; + } + + const rapidjson::Document& data = baseContainer->getData(); + if (!data.HasMember("_typeName") || !data["_typeName"].IsString()) + { + return baseContainer; + } + + const char* typeName = data["_typeName"].GetString(); + AssetReference ref = baseContainer->getReference(); + + DataContainer* derived = DataContainerFactory::createDataContainer(typeName, ref); + if (!derived) + { + return baseContainer; + } + + derived->deserializeJson(data); + delete baseContainer; + return derived; +} diff --git a/Engine_Master_UPC/ModuleAssets.h b/Engine_Master_UPC/ModuleAssets.h index 91b4d9ce..4e0b0fa5 100644 --- a/Engine_Master_UPC/ModuleAssets.h +++ b/Engine_Master_UPC/ModuleAssets.h @@ -14,7 +14,8 @@ #include #include "FileIO.h" #include "Importer.h" -#include +#include "DataContainer.h" +#include "DataContainerFactory.h" class AssetScanner; @@ -190,6 +191,7 @@ friend PrefabManager; bool createStateMachineFromGltf(const std::filesystem::path& gltfPath); private: + DataContainer* resolveDataContainerType(DataContainer* baseContainer) const; UID findUID(const std::filesystem::path& sourcePath) const; template @@ -217,6 +219,16 @@ friend PrefabManager; std::shared_ptr asset(importer->createAssetInstance(ref)); importer->load(buffer.data(), asset.get()); + + if (ref.m_type == AssetType::DATA_CONTAINER) + { + DataContainer* dc = resolveDataContainerType(static_cast(asset.get())); + if (dc != static_cast(asset.get())) + { + asset.reset(dc); + } + } + m_assets.insert(ref.m_uid, asset); return std::static_pointer_cast(asset); diff --git a/Engine_Master_UPC/ModuleEditor.cpp b/Engine_Master_UPC/ModuleEditor.cpp index 46922ff4..cd237436 100644 --- a/Engine_Master_UPC/ModuleEditor.cpp +++ b/Engine_Master_UPC/ModuleEditor.cpp @@ -29,6 +29,9 @@ #include "ModuleGameView.h" #include "ModuleAssets.h" #include "Mouse.h" +#include "DataContainerFactory.h" +#include "ContentRegistry.h" +#include "CommandCreateDataContainer.h" #include @@ -312,7 +315,7 @@ void ModuleEditor::mainMenuBar() if (ImGui::BeginMenu("Window")) { - // ---- New Window submenu — spawn additional instances ---- + // ---- New Window submenu – spawn additional instances ---- if (!m_windowFactories.empty()) { ImGui::Separator(); @@ -332,6 +335,33 @@ void ModuleEditor::mainMenuBar() ImGui::EndMenu(); } + if (ImGui::BeginMenu("Asset")) + { + const auto& dcRegistry = DataContainerFactory::getAllRegistered(); + if (!dcRegistry.empty()) + { + for (const auto& entry : dcRegistry) + { + if (ImGui::MenuItem(entry.displayName.c_str())) + { + std::filesystem::path assetsDir = ASSETS_FOLDER; + if (assetsDir.empty()) + { + assetsDir = std::filesystem::current_path() / "Assets"; + } + std::string assetName = std::string("New_") + entry.name; + CommandCreateDataContainer(assetsDir, entry.name, assetName, entry.extension).run(); + } + } + } + else + { + ImGui::TextDisabled("No asset types registered"); + } + + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); } diff --git a/GameScripts/BoundConfig.cpp b/GameScripts/BoundConfig.cpp new file mode 100644 index 00000000..abd3a0b4 --- /dev/null +++ b/GameScripts/BoundConfig.cpp @@ -0,0 +1,44 @@ +#include "pch.h" +#include "BoundConfig.h" + +IMPLEMENT_DATACONTAINER(BoundConfig, ".config") + +bool BoundConfig::deserializeJson(const rapidjson::Value& obj) +{ + if (!obj.IsObject()) + { + return false; + } + + m_data.CopyFrom(obj, m_data.GetAllocator()); + + if (obj.HasMember("MinDistance") && obj["MinDistance"].IsFloat()) + m_minDistance = obj["MinDistance"].GetFloat(); + if (obj.HasMember("DistanceDamage") && obj["DistanceDamage"].IsFloat()) + m_distanceDamage = obj["DistanceDamage"].GetFloat(); + if (obj.HasMember("DistanceInstaKill") && obj["DistanceInstaKill"].IsFloat()) + m_distanceInstaKill = obj["DistanceInstaKill"].GetFloat(); + if (obj.HasMember("BaseDamage") && obj["BaseDamage"].IsFloat()) + m_baseDamage = obj["BaseDamage"].GetFloat(); + if (obj.HasMember("MaxDamage") && obj["MaxDamage"].IsFloat()) + m_maxDamage = obj["MaxDamage"].GetFloat(); + if (obj.HasMember("RadiusThreshold") && obj["RadiusThreshold"].IsFloat()) + m_radiusThreshold = obj["RadiusThreshold"].GetFloat(); + + return true; +} + +rapidjson::Value BoundConfig::getJson(rapidjson::Document::AllocatorType& allocator) const +{ + rapidjson::Value obj(rapidjson::kObjectType); + + obj.AddMember("_typeName", rapidjson::Value("BoundConfig", allocator), allocator); + obj.AddMember("MinDistance", m_minDistance, allocator); + obj.AddMember("DistanceDamage", m_distanceDamage, allocator); + obj.AddMember("DistanceInstaKill", m_distanceInstaKill, allocator); + obj.AddMember("BaseDamage", m_baseDamage, allocator); + obj.AddMember("MaxDamage", m_maxDamage, allocator); + obj.AddMember("RadiusThreshold", m_radiusThreshold, allocator); + + return obj; +} \ No newline at end of file diff --git a/GameScripts/BoundConfig.h b/GameScripts/BoundConfig.h new file mode 100644 index 00000000..08b25197 --- /dev/null +++ b/GameScripts/BoundConfig.h @@ -0,0 +1,29 @@ +#pragma once + +#include "DataContainerAPI.h" + +class BoundConfig : public DataContainer +{ + DECLARE_DATACONTAINER(BoundConfig) + +public: + BoundConfig() = default; + explicit BoundConfig(AssetReference& id) + : DataContainer(id) + { + } + + const char* getTypeName() const override { return "BoundConfig"; } + const char* getDisplayTypeName() const override { return "Bound Config"; } + const char* getFileExtension() const override { return ".config"; } + + bool deserializeJson(const rapidjson::Value& obj) override; + rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const override; + + float m_minDistance = 70.0f; + float m_distanceDamage = 80.0f; + float m_distanceInstaKill = 100.0f; + float m_baseDamage = 20.0f; + float m_maxDamage = 40.0f; + float m_radiusThreshold = 2.0f; +}; \ No newline at end of file diff --git a/GameScripts/GameScripts.vcxproj b/GameScripts/GameScripts.vcxproj index b9f0bbcf..cb22083e 100644 --- a/GameScripts/GameScripts.vcxproj +++ b/GameScripts/GameScripts.vcxproj @@ -249,6 +249,7 @@ + @@ -310,6 +311,7 @@ + From c63bc2401bef11323ed8aaeed4ed339d37a307f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Wed, 20 May 2026 23:50:08 +0200 Subject: [PATCH 04/34] System fully working and we can modify the members throw the inspector --- .../CommandCreateDataContainer.cpp | 32 ++++++++++++--- .../CommandCreateDataContainer.h | 5 +-- Engine_Master_UPC/DataContainer.h | 21 ++++++++-- Engine_Master_UPC/DataContainerAPI.h | 41 ++++++++++--------- Engine_Master_UPC/DataContainerAutoRegister.h | 9 ++-- Engine_Master_UPC/DataContainerFactory.cpp | 6 +-- Engine_Master_UPC/DataContainerFactory.h | 4 +- Engine_Master_UPC/DataContainerRegistry.h | 3 +- Engine_Master_UPC/EngineAPI.cpp | 4 +- Engine_Master_UPC/EngineAPI.h | 2 +- Engine_Master_UPC/Extensions.h | 1 - Engine_Master_UPC/ImporterDataContainer.cpp | 17 +------- Engine_Master_UPC/ImporterDataContainer.h | 1 - Engine_Master_UPC/ModuleAssets.cpp | 20 +++++---- Engine_Master_UPC/ModuleAssets.h | 7 ++-- Engine_Master_UPC/ModuleEditor.cpp | 2 +- Engine_Master_UPC/WindowFileDialog.cpp | 2 +- GameScripts/BoundConfig.cpp | 2 +- GameScripts/BoundConfig.h | 4 -- 19 files changed, 99 insertions(+), 84 deletions(-) diff --git a/Engine_Master_UPC/CommandCreateDataContainer.cpp b/Engine_Master_UPC/CommandCreateDataContainer.cpp index 6e118034..722d0e99 100644 --- a/Engine_Master_UPC/CommandCreateDataContainer.cpp +++ b/Engine_Master_UPC/CommandCreateDataContainer.cpp @@ -4,6 +4,8 @@ #include "Application.h" #include "ModuleAssets.h" #include "DataContainerFactory.h" +#include "DataContainer.h" +#include "Extensions.h" #include "UID.h" #include @@ -15,18 +17,16 @@ CommandCreateDataContainer::CommandCreateDataContainer( const std::filesystem::path& targetDir, const std::string& typeName, - const std::string& assetName, - const std::string& extension) + const std::string& assetName) : m_targetDir(targetDir) , m_typeName(typeName) , m_assetName(assetName) - , m_extension(extension) { } void CommandCreateDataContainer::run() { - std::filesystem::path filePath = m_targetDir / (m_assetName + m_extension); + std::filesystem::path filePath = m_targetDir / (m_assetName + DATA_CONTAINER_EXTENSION); if (std::filesystem::exists(filePath)) { @@ -40,6 +40,28 @@ void CommandCreateDataContainer::run() doc.AddMember("_typeName", rapidjson::Value(m_typeName.c_str(), allocator), allocator); + AssetReference tempRef(INVALID_UID); + DataContainer* instance = DataContainerFactory::createDataContainer(m_typeName, tempRef); + if (instance) + { + rapidjson::Value instanceJson = instance->getJson(allocator); + if (instanceJson.IsObject()) + { + for (auto it = instanceJson.MemberBegin(); it != instanceJson.MemberEnd(); ++it) + { + if (!doc.HasMember(it->name.GetString())) + { + doc.AddMember( + rapidjson::Value(it->name, allocator), + rapidjson::Value(it->value, allocator), + allocator + ); + } + } + } + delete instance; + } + rapidjson::StringBuffer buffer; rapidjson::PrettyWriter writer(buffer); doc.Accept(writer); @@ -55,4 +77,4 @@ void CommandCreateDataContainer::run() file.close(); app->getModuleAssets()->refresh(); -} +} \ No newline at end of file diff --git a/Engine_Master_UPC/CommandCreateDataContainer.h b/Engine_Master_UPC/CommandCreateDataContainer.h index ea9ab3f0..3f0e54ab 100644 --- a/Engine_Master_UPC/CommandCreateDataContainer.h +++ b/Engine_Master_UPC/CommandCreateDataContainer.h @@ -7,7 +7,7 @@ class CommandCreateDataContainer : public ICommand { public: - CommandCreateDataContainer(const std::filesystem::path& targetDir, const std::string& typeName, const std::string& assetName, const std::string& extension); + CommandCreateDataContainer(const std::filesystem::path& targetDir, const std::string& typeName, const std::string& assetName); void run() override; @@ -15,5 +15,4 @@ class CommandCreateDataContainer : public ICommand std::filesystem::path m_targetDir; std::string m_typeName; std::string m_assetName; - std::string m_extension; -}; +}; \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainer.h b/Engine_Master_UPC/DataContainer.h index 111b6446..0a2edde2 100644 --- a/Engine_Master_UPC/DataContainer.h +++ b/Engine_Master_UPC/DataContainer.h @@ -5,6 +5,8 @@ #pragma warning(disable: 4251) #include +#include +#include class ImporterDataContainer; @@ -27,12 +29,23 @@ class ENGINE_API DataContainer : public Asset const rapidjson::Document& getData() const { return m_data; } rapidjson::Document& getDataMutable() { return m_data; } - virtual const char* getTypeName() const { return "DataContainer"; } - virtual const char* getDisplayTypeName() const { return "Data Container"; } - virtual const char* getFileExtension() const { return ".datacontainer"; } + virtual const char* getTypeName() const + { + const char* name = typeid(*this).name(); +#ifdef _MSC_VER + if (std::strncmp(name, "class ", 6) == 0) return name + 6; + if (std::strncmp(name, "struct ", 7) == 0) return name + 7; +#endif + return name; + } + + virtual const char* getDisplayTypeName() const + { + return getTypeName(); + } protected: rapidjson::Document m_data; }; -#pragma warning(pop) +#pragma warning(pop) \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainerAPI.h b/Engine_Master_UPC/DataContainerAPI.h index 5579224a..e93518a8 100644 --- a/Engine_Master_UPC/DataContainerAPI.h +++ b/Engine_Master_UPC/DataContainerAPI.h @@ -2,26 +2,27 @@ // Include this header in your external project to create custom DataContainer assets // (similar to Unity ScriptableObjects) - -#include "DataContainer.h" -#include "DataContainerAutoRegister.h" -#include "EngineAPI.h" - -// Usage example: // -// In your .h file: -// class MyConfig : public DataContainer { -// public: -// DECLARE_DATACONTAINER(MyConfig) -// MyConfig() = default; -// explicit MyConfig(AssetReference& id) : DataContainer(id) {} -// const char* getTypeName() const override { return "MyConfig"; } -// const char* getDisplayTypeName() const override { return "My Config"; } -// const char* getFileExtension() const override { return ".myconfig"; } -// // Add your typed accessor methods here... -// }; +// All DataContainer assets use the .datacontainer file extension. +// Derived classes are identified by _typeName in the JSON file. // -// In your .cpp file: -// IMPLEMENT_DATACONTAINER(MyConfig, ".myconfig") +// Usage: +// .h file: +// class MyConfig : public DataContainer { +// DECLARE_DATACONTAINER(MyConfig) +// public: +// MyConfig() = default; +// explicit MyConfig(AssetReference& id) : DataContainer(id) {} +// bool deserializeJson(const rapidjson::Value& obj) override; +// rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const override; +// float m_value = 10.0f; +// }; +// .cpp file: +// IMPLEMENT_DATACONTAINER(MyConfig) +// // override deserializeJson/getJson to serialize members // -// The class will auto-register and appear in the FileDialog right-click "Create" menu. +// The class auto-registers and appears in the FileDialog "Create" menu and "Asset" top menu. + +#include "DataContainer.h" +#include "DataContainerAutoRegister.h" +#include "EngineAPI.h" \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainerAutoRegister.h b/Engine_Master_UPC/DataContainerAutoRegister.h index 55c163bd..8ad572a2 100644 --- a/Engine_Master_UPC/DataContainerAutoRegister.h +++ b/Engine_Master_UPC/DataContainerAutoRegister.h @@ -5,9 +5,9 @@ class DataContainerAutoRegister { public: - DataContainerAutoRegister(const char* name, const char* displayName, const char* extension, DataContainerCreator creator) + DataContainerAutoRegister(const char* name, const char* displayName, DataContainerCreator creator) { - registerDataContainer(name, displayName, extension, creator); + registerDataContainer(name, displayName, creator); } }; @@ -15,7 +15,7 @@ class DataContainerAutoRegister public: \ static DataContainer* Create(AssetReference& uid); -#define IMPLEMENT_DATACONTAINER(TypeName, Extension) \ +#define IMPLEMENT_DATACONTAINER(TypeName) \ DataContainer* TypeName::Create(AssetReference& uid) \ { \ return new TypeName(uid); \ @@ -23,6 +23,5 @@ public: \ static DataContainerAutoRegister s_autoRegister_##TypeName( \ #TypeName, \ #TypeName, \ - Extension, \ &TypeName::Create \ - ); + ); \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainerFactory.cpp b/Engine_Master_UPC/DataContainerFactory.cpp index a9860886..d5ee326c 100644 --- a/Engine_Master_UPC/DataContainerFactory.cpp +++ b/Engine_Master_UPC/DataContainerFactory.cpp @@ -4,7 +4,7 @@ std::vector DataContainerFactory::m_registry; -void DataContainerFactory::registerDataContainer(const std::string& name, const std::string& displayName, const std::string& extension, DataContainerCreator creator) +void DataContainerFactory::registerDataContainer(const std::string& name, const std::string& displayName, DataContainerCreator creator) { for (DataContainerRegistry& entry : m_registry) { @@ -15,7 +15,7 @@ void DataContainerFactory::registerDataContainer(const std::string& name, const } } - m_registry.push_back({ name, displayName, extension, creator }); + m_registry.push_back({ name, displayName, creator }); } DataContainer* DataContainerFactory::createDataContainer(const std::string& name, AssetReference& uid) @@ -47,4 +47,4 @@ bool DataContainerFactory::isDataContainerRegistered(const std::string& name) const std::vector& DataContainerFactory::getAllRegistered() { return m_registry; -} +} \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainerFactory.h b/Engine_Master_UPC/DataContainerFactory.h index df303f71..bbaf52a4 100644 --- a/Engine_Master_UPC/DataContainerFactory.h +++ b/Engine_Master_UPC/DataContainerFactory.h @@ -8,11 +8,11 @@ struct AssetReference; class DataContainerFactory { public: - static void registerDataContainer(const std::string& name, const std::string& displayName, const std::string& extension, DataContainerCreator creator); + static void registerDataContainer(const std::string& name, const std::string& displayName, DataContainerCreator creator); static DataContainer* createDataContainer(const std::string& name, AssetReference& uid); static bool isDataContainerRegistered(const std::string& name); static const std::vector& getAllRegistered(); private: static std::vector m_registry; -}; +}; \ No newline at end of file diff --git a/Engine_Master_UPC/DataContainerRegistry.h b/Engine_Master_UPC/DataContainerRegistry.h index 5d3ff158..af9130b5 100644 --- a/Engine_Master_UPC/DataContainerRegistry.h +++ b/Engine_Master_UPC/DataContainerRegistry.h @@ -7,6 +7,5 @@ struct DataContainerRegistry { std::string name; std::string displayName; - std::string extension; DataContainerCreator creator; -}; +}; \ No newline at end of file diff --git a/Engine_Master_UPC/EngineAPI.cpp b/Engine_Master_UPC/EngineAPI.cpp index f74406d3..ecd4b619 100644 --- a/Engine_Master_UPC/EngineAPI.cpp +++ b/Engine_Master_UPC/EngineAPI.cpp @@ -45,9 +45,9 @@ void registerScript(const char* scriptName, ScriptCreator creator) ScriptFactory::registerScript(scriptName, creator); } -void registerDataContainer(const char* name, const char* displayName, const char* extension, DataContainerCreator creator) +void registerDataContainer(const char* name, const char* displayName, DataContainerCreator creator) { - DataContainerFactory::registerDataContainer(name, displayName, extension, creator); + DataContainerFactory::registerDataContainer(name, displayName, creator); } namespace GameObjectAPI diff --git a/Engine_Master_UPC/EngineAPI.h b/Engine_Master_UPC/EngineAPI.h index 73036685..b3ec1071 100644 --- a/Engine_Master_UPC/EngineAPI.h +++ b/Engine_Master_UPC/EngineAPI.h @@ -28,7 +28,7 @@ class Transform2D; struct HapticEffectDefinition; ENGINE_API void registerScript(const char* scriptName, ScriptCreator creator); -ENGINE_API void registerDataContainer(const char* name, const char* displayName, const char* extension, DataContainerCreator creator); +ENGINE_API void registerDataContainer(const char* name, const char* displayName, DataContainerCreator creator); namespace GameObjectAPI { diff --git a/Engine_Master_UPC/Extensions.h b/Engine_Master_UPC/Extensions.h index f9c85969..ce474158 100644 --- a/Engine_Master_UPC/Extensions.h +++ b/Engine_Master_UPC/Extensions.h @@ -7,7 +7,6 @@ constexpr const char* ANIMATION_EXTENSION = ".anim"; constexpr const char* ANIMATION_STATE_MACHINE_EXTENSION = ".statemachine"; constexpr const char* SCENE_EXTENSION = ".scene"; constexpr const char* DATA_CONTAINER_EXTENSION = ".datacontainer"; -constexpr const char* CONFIG_EXTENSION = ".config"; constexpr const char* PNG_EXTENSION = ".png"; constexpr const char* JPG_EXTENSION = ".jpg"; diff --git a/Engine_Master_UPC/ImporterDataContainer.cpp b/Engine_Master_UPC/ImporterDataContainer.cpp index 42d81f92..e7e9ca9b 100644 --- a/Engine_Master_UPC/ImporterDataContainer.cpp +++ b/Engine_Master_UPC/ImporterDataContainer.cpp @@ -14,22 +14,7 @@ bool ImporterDataContainer::canImport(const std::filesystem::path& path) const { - const std::string ext = path.extension().string(); - if (ext == DATA_CONTAINER_EXTENSION || ext == CONFIG_EXTENSION) - { - return true; - } - - const auto& registry = DataContainerFactory::getAllRegistered(); - for (const auto& entry : registry) - { - if (ext == entry.extension) - { - return true; - } - } - - return false; + return path.extension().string() == DATA_CONTAINER_EXTENSION; } Asset* ImporterDataContainer::createAssetInstance(AssetReference& uid) const diff --git a/Engine_Master_UPC/ImporterDataContainer.h b/Engine_Master_UPC/ImporterDataContainer.h index 65184fbd..faf7f37e 100644 --- a/Engine_Master_UPC/ImporterDataContainer.h +++ b/Engine_Master_UPC/ImporterDataContainer.h @@ -1,7 +1,6 @@ #pragma once #include "ImporterNative.h" #include "DataContainer.h" -#include "DataContainerFactory.h" #include "Extensions.h" class ImporterDataContainer diff --git a/Engine_Master_UPC/ModuleAssets.cpp b/Engine_Master_UPC/ModuleAssets.cpp index 8c5bba98..cd52d012 100644 --- a/Engine_Master_UPC/ModuleAssets.cpp +++ b/Engine_Master_UPC/ModuleAssets.cpp @@ -15,8 +15,6 @@ #include "ImporterFont.h" #include "ImporterScene.h" #include "ImporterDataContainer.h" -#include "DataContainerFactory.h" -#include "DataContainer.h" #include "MD5.h" #include "AssetScanner.h" @@ -150,11 +148,16 @@ void ModuleAssets::importAsset(const std::filesystem::path& sourcePath, AssetRef if (reference.m_type == AssetType::DATA_CONTAINER) { - DataContainer* dc = resolveDataContainerType(static_cast(asset.get())); - if (dc != static_cast(asset.get())) + DataContainer* baseDc = static_cast(asset.release()); + DataContainer* derivedDc = resolveDataContainerType(baseDc); + if (derivedDc) { - asset.release(); - asset.reset(dc); + delete baseDc; + asset.reset(derivedDc); + } + else + { + asset.reset(baseDc); } } @@ -614,7 +617,7 @@ DataContainer* ModuleAssets::resolveDataContainerType(DataContainer* baseContain const rapidjson::Document& data = baseContainer->getData(); if (!data.HasMember("_typeName") || !data["_typeName"].IsString()) { - return baseContainer; + return nullptr; } const char* typeName = data["_typeName"].GetString(); @@ -623,10 +626,9 @@ DataContainer* ModuleAssets::resolveDataContainerType(DataContainer* baseContain DataContainer* derived = DataContainerFactory::createDataContainer(typeName, ref); if (!derived) { - return baseContainer; + return nullptr; } derived->deserializeJson(data); - delete baseContainer; return derived; } diff --git a/Engine_Master_UPC/ModuleAssets.h b/Engine_Master_UPC/ModuleAssets.h index 4e0b0fa5..de4a9851 100644 --- a/Engine_Master_UPC/ModuleAssets.h +++ b/Engine_Master_UPC/ModuleAssets.h @@ -222,10 +222,11 @@ friend PrefabManager; if (ref.m_type == AssetType::DATA_CONTAINER) { - DataContainer* dc = resolveDataContainerType(static_cast(asset.get())); - if (dc != static_cast(asset.get())) + DataContainer* baseDc = static_cast(asset.get()); + DataContainer* derivedDc = resolveDataContainerType(baseDc); + if (derivedDc) { - asset.reset(dc); + asset = std::shared_ptr(derivedDc); } } diff --git a/Engine_Master_UPC/ModuleEditor.cpp b/Engine_Master_UPC/ModuleEditor.cpp index cd237436..8352f3cd 100644 --- a/Engine_Master_UPC/ModuleEditor.cpp +++ b/Engine_Master_UPC/ModuleEditor.cpp @@ -350,7 +350,7 @@ void ModuleEditor::mainMenuBar() assetsDir = std::filesystem::current_path() / "Assets"; } std::string assetName = std::string("New_") + entry.name; - CommandCreateDataContainer(assetsDir, entry.name, assetName, entry.extension).run(); + CommandCreateDataContainer(assetsDir, entry.name, assetName).run(); } } } diff --git a/Engine_Master_UPC/WindowFileDialog.cpp b/Engine_Master_UPC/WindowFileDialog.cpp index 24379454..66ca0b7c 100644 --- a/Engine_Master_UPC/WindowFileDialog.cpp +++ b/Engine_Master_UPC/WindowFileDialog.cpp @@ -391,7 +391,7 @@ void WindowFileDialog::drawAssetGrid(DirectoryEntry* directory) if (ImGui::MenuItem(entry.displayName.c_str())) { std::string assetName = entry.displayName + "_New"; - CommandCreateDataContainer(m_currentDirectory, entry.name, assetName, entry.extension).run(); + CommandCreateDataContainer(m_currentDirectory, entry.name, assetName).run(); } } ImGui::EndMenu(); diff --git a/GameScripts/BoundConfig.cpp b/GameScripts/BoundConfig.cpp index abd3a0b4..9864f3f6 100644 --- a/GameScripts/BoundConfig.cpp +++ b/GameScripts/BoundConfig.cpp @@ -1,7 +1,7 @@ #include "pch.h" #include "BoundConfig.h" -IMPLEMENT_DATACONTAINER(BoundConfig, ".config") +IMPLEMENT_DATACONTAINER(BoundConfig) bool BoundConfig::deserializeJson(const rapidjson::Value& obj) { diff --git a/GameScripts/BoundConfig.h b/GameScripts/BoundConfig.h index 08b25197..e0158932 100644 --- a/GameScripts/BoundConfig.h +++ b/GameScripts/BoundConfig.h @@ -13,10 +13,6 @@ class BoundConfig : public DataContainer { } - const char* getTypeName() const override { return "BoundConfig"; } - const char* getDisplayTypeName() const override { return "Bound Config"; } - const char* getFileExtension() const override { return ".config"; } - bool deserializeJson(const rapidjson::Value& obj) override; rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const override; From 9f374065cc883da080796ced39c2701e89c142d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Thu, 21 May 2026 10:33:23 +0200 Subject: [PATCH 05/34] Data Container now can be saved when we apply changes --- Engine_Master_UPC/DataContainer.cpp | 12 ++++++++++++ Engine_Master_UPC/DataContainer.h | 2 ++ Engine_Master_UPC/DataContainerAPI.h | 3 ++- Engine_Master_UPC/ImporterDataContainer.cpp | 16 ++++++++++++++-- GameScripts/BoundConfig.cpp | 19 +++++++++++++++++++ GameScripts/BoundConfig.h | 1 + 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/Engine_Master_UPC/DataContainer.cpp b/Engine_Master_UPC/DataContainer.cpp index d11a9e6a..f64e98c9 100644 --- a/Engine_Master_UPC/DataContainer.cpp +++ b/Engine_Master_UPC/DataContainer.cpp @@ -1,5 +1,7 @@ #include "Globals.h" #include "DataContainer.h" +#include "Application.h" +#include "ModuleAssets.h" #include @@ -26,6 +28,16 @@ void DataContainer::drawUI() ImGui::TextDisabled("UID: %llu", static_cast(getUID())); + ImGui::Spacing(); + + if (ImGui::Button("Save")) + { + app->getModuleAssets()->save(*this); + } + + ImGui::SameLine(); + ImGui::TextDisabled("(Ctrl+S)"); + ImGui::Spacing(); ImGui::SeparatorText("Properties"); diff --git a/Engine_Master_UPC/DataContainer.h b/Engine_Master_UPC/DataContainer.h index 0a2edde2..6c39b98b 100644 --- a/Engine_Master_UPC/DataContainer.h +++ b/Engine_Master_UPC/DataContainer.h @@ -24,6 +24,8 @@ class ENGINE_API DataContainer : public Asset virtual rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const; virtual bool deserializeJson(const rapidjson::Value& obj); + + virtual void syncFromData() {} void drawUI() override; const rapidjson::Document& getData() const { return m_data; } diff --git a/Engine_Master_UPC/DataContainerAPI.h b/Engine_Master_UPC/DataContainerAPI.h index e93518a8..96d3d8a0 100644 --- a/Engine_Master_UPC/DataContainerAPI.h +++ b/Engine_Master_UPC/DataContainerAPI.h @@ -15,11 +15,12 @@ // explicit MyConfig(AssetReference& id) : DataContainer(id) {} // bool deserializeJson(const rapidjson::Value& obj) override; // rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const override; +// void syncFromData() override; // sync typed members from m_data after inspector edits // float m_value = 10.0f; // }; // .cpp file: // IMPLEMENT_DATACONTAINER(MyConfig) -// // override deserializeJson/getJson to serialize members +// // override deserializeJson, getJson, and syncFromData to handle your members // // The class auto-registers and appears in the FileDialog "Create" menu and "Asset" top menu. diff --git a/Engine_Master_UPC/ImporterDataContainer.cpp b/Engine_Master_UPC/ImporterDataContainer.cpp index e7e9ca9b..426c5fd1 100644 --- a/Engine_Master_UPC/ImporterDataContainer.cpp +++ b/Engine_Master_UPC/ImporterDataContainer.cpp @@ -24,9 +24,15 @@ Asset* ImporterDataContainer::createAssetInstance(AssetReference& uid) const bool ImporterDataContainer::saveNative(const DataContainer* asset, const std::filesystem::path& path) { + const_cast(asset)->syncFromData(); + + rapidjson::Document doc; + rapidjson::Value json = asset->getJson(doc.GetAllocator()); + doc.Swap(json); + rapidjson::StringBuffer buffer; rapidjson::PrettyWriter writer(buffer); - asset->m_data.Accept(writer); + doc.Accept(writer); std::ofstream file(path); if (!file.is_open()) @@ -71,9 +77,15 @@ bool ImporterDataContainer::importNative(const std::filesystem::path& path, Data uint64_t ImporterDataContainer::saveTyped(const DataContainer* source, uint8_t** outBuffer) { + const_cast(source)->syncFromData(); + + rapidjson::Document doc; + rapidjson::Value json = source->getJson(doc.GetAllocator()); + doc.Swap(json); + rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); - source->m_data.Accept(writer); + doc.Accept(writer); const std::string jsonStr = buffer.GetString(); const uint64_t size = sizeof(uint32_t) + sizeof(uint32_t) + jsonStr.size(); diff --git a/GameScripts/BoundConfig.cpp b/GameScripts/BoundConfig.cpp index 9864f3f6..9e013a49 100644 --- a/GameScripts/BoundConfig.cpp +++ b/GameScripts/BoundConfig.cpp @@ -41,4 +41,23 @@ rapidjson::Value BoundConfig::getJson(rapidjson::Document::AllocatorType& alloca obj.AddMember("RadiusThreshold", m_radiusThreshold, allocator); return obj; +} + +void BoundConfig::syncFromData() +{ + if (!m_data.IsObject()) + return; + + if (m_data.HasMember("MinDistance") && m_data["MinDistance"].IsFloat()) + m_minDistance = m_data["MinDistance"].GetFloat(); + if (m_data.HasMember("DistanceDamage") && m_data["DistanceDamage"].IsFloat()) + m_distanceDamage = m_data["DistanceDamage"].GetFloat(); + if (m_data.HasMember("DistanceInstaKill") && m_data["DistanceInstaKill"].IsFloat()) + m_distanceInstaKill = m_data["DistanceInstaKill"].GetFloat(); + if (m_data.HasMember("BaseDamage") && m_data["BaseDamage"].IsFloat()) + m_baseDamage = m_data["BaseDamage"].GetFloat(); + if (m_data.HasMember("MaxDamage") && m_data["MaxDamage"].IsFloat()) + m_maxDamage = m_data["MaxDamage"].GetFloat(); + if (m_data.HasMember("RadiusThreshold") && m_data["RadiusThreshold"].IsFloat()) + m_radiusThreshold = m_data["RadiusThreshold"].GetFloat(); } \ No newline at end of file diff --git a/GameScripts/BoundConfig.h b/GameScripts/BoundConfig.h index e0158932..2c75f1ac 100644 --- a/GameScripts/BoundConfig.h +++ b/GameScripts/BoundConfig.h @@ -15,6 +15,7 @@ class BoundConfig : public DataContainer bool deserializeJson(const rapidjson::Value& obj) override; rapidjson::Value getJson(rapidjson::Document::AllocatorType& allocator) const override; + void syncFromData() override; float m_minDistance = 70.0f; float m_distanceDamage = 80.0f; From 81b3aa9966a2ac3b0cbe9bcdb9ede64c1c33a76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Thu, 21 May 2026 14:20:16 +0200 Subject: [PATCH 06/34] Import and export of the data containers working --- Engine_Master_UPC/DataContainerExporter.cpp | 184 ++++++++++++++++++++ Engine_Master_UPC/DataContainerExporter.h | 15 ++ Engine_Master_UPC/Engine.vcxproj | 2 + Engine_Master_UPC/Engine.vcxproj.filters | 17 +- Engine_Master_UPC/ModuleEditor.cpp | 54 ++++++ Engine_Master_UPC/ModuleEditor.h | 7 + 6 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 Engine_Master_UPC/DataContainerExporter.cpp create mode 100644 Engine_Master_UPC/DataContainerExporter.h diff --git a/Engine_Master_UPC/DataContainerExporter.cpp b/Engine_Master_UPC/DataContainerExporter.cpp new file mode 100644 index 00000000..8d74814a --- /dev/null +++ b/Engine_Master_UPC/DataContainerExporter.cpp @@ -0,0 +1,184 @@ +#include "Globals.h" +#include "DataContainerExporter.h" + +#include "AssetsDictionary.h" +#include "Extensions.h" +#include "Application.h" +#include "ModuleAssets.h" + +#include +#include +#include +#include "rapidjson/filereadstream.h" + +#include +#include +#include + +namespace fs = std::filesystem; + +bool DataContainerExporter::exportToJson(const fs::path& outputPath) +{ + rapidjson::Document root; + root.SetObject(); + rapidjson::Document::AllocatorType& allocator = root.GetAllocator(); + + fs::path assetsRoot = ASSETS_FOLDER; + if (!assetsRoot.is_absolute()) + { + assetsRoot = fs::absolute(assetsRoot); + } + + if (!fs::exists(assetsRoot)) + { + DEBUG_ERROR("[DataContainerExporter] Assets folder '%s' not found.", assetsRoot.string().c_str()); + return false; + } + + // Scan recursively for .datacontainer files + for (const auto& entry : fs::recursive_directory_iterator(assetsRoot)) + { + if (!entry.is_regular_file()) + continue; + + const fs::path& filePath = entry.path(); + if (filePath.extension().string() != DATA_CONTAINER_EXTENSION) + continue; + + // Read the .datacontainer file + FILE* fp = std::fopen(filePath.string().c_str(), "rb"); + if (!fp) + { + DEBUG_WARN("[DataContainerExporter] Could not open '%s'.", filePath.string().c_str()); + continue; + } + + char readBuffer[65536]; + rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + rapidjson::Document doc; + doc.ParseStream(is); + std::fclose(fp); + + if (doc.HasParseError() || !doc.IsObject()) + { + DEBUG_WARN("[DataContainerExporter] Parse error in '%s'.", filePath.string().c_str()); + continue; + } + + // Use filename stem as key + std::string key = filePath.stem().string(); + rapidjson::Value keyVal(key.c_str(), allocator); + + // Deep-copy the document's members into a new value + rapidjson::Value obj(rapidjson::kObjectType); + for (auto it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) + { + rapidjson::Value name(it->name.GetString(), allocator); + rapidjson::Value value; + value.CopyFrom(it->value, allocator); + obj.AddMember(name, value, allocator); + } + + root.AddMember(keyVal, obj, allocator); + + DEBUG_LOG("[DataContainerExporter] Exported '%s'.", key.c_str()); + } + + if (root.MemberCount() == 0) + { + DEBUG_WARN("[DataContainerExporter] No .datacontainer files found to export."); + return false; + } + + // Write combined JSON + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + root.Accept(writer); + + std::ofstream file(outputPath); + if (!file.is_open()) + { + DEBUG_ERROR("[DataContainerExporter] Could not write '%s'.", outputPath.string().c_str()); + return false; + } + + file << buffer.GetString(); + file.close(); + + DEBUG_LOG("[DataContainerExporter] Exported %llu data assets to '%s'.", + static_cast(root.MemberCount()), outputPath.string().c_str()); + return true; +} + +bool DataContainerExporter::importFromJson(const fs::path& inputPath) +{ + FILE* fp = std::fopen(inputPath.string().c_str(), "rb"); + if (!fp) + { + DEBUG_ERROR("[DataContainerExporter] Could not open '%s'.", inputPath.string().c_str()); + return false; + } + + char readBuffer[65536]; + rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + rapidjson::Document root; + root.ParseStream(is); + std::fclose(fp); + + if (root.HasParseError() || !root.IsObject()) + { + DEBUG_ERROR("[DataContainerExporter] Parse error in '%s'.", inputPath.string().c_str()); + return false; + } + + fs::path assetsRoot = ASSETS_FOLDER; + if (!assetsRoot.is_absolute()) + { + assetsRoot = fs::absolute(assetsRoot); + } + + if (!fs::exists(assetsRoot)) + { + DEBUG_ERROR("[DataContainerExporter] Assets folder '%s' not found.", assetsRoot.string().c_str()); + return false; + } + + size_t importedCount = 0; + + for (auto it = root.MemberBegin(); it != root.MemberEnd(); ++it) + { + if (!it->value.IsObject()) + { + DEBUG_WARN("[DataContainerExporter] Skipping '%s': value is not an object.", it->name.GetString()); + continue; + } + + std::string name = it->name.GetString(); + fs::path filePath = assetsRoot / (name + DATA_CONTAINER_EXTENSION); + + // Serialize this entry back to JSON + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + it->value.Accept(writer); + + std::ofstream file(filePath); + if (!file.is_open()) + { + DEBUG_ERROR("[DataContainerExporter] Could not write '%s'.", filePath.string().c_str()); + continue; + } + + file << buffer.GetString(); + file.close(); + + DEBUG_LOG("[DataContainerExporter] Imported '%s'.", name.c_str()); + ++importedCount; + } + + // Refresh the asset system to pick up new/changed files + app->getModuleAssets()->refresh(); + + DEBUG_LOG("[DataContainerExporter] Imported %zu data assets from '%s'.", + importedCount, inputPath.string().c_str()); + return importedCount > 0; +} diff --git a/Engine_Master_UPC/DataContainerExporter.h b/Engine_Master_UPC/DataContainerExporter.h new file mode 100644 index 00000000..b9e8434c --- /dev/null +++ b/Engine_Master_UPC/DataContainerExporter.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +class DataContainerExporter +{ +public: + // Scans ASSETS_FOLDER for all .datacontainer files and writes them as a single + // JSON object keyed by filename stem (e.g. "MyConfig" -> { ... }). + static bool exportToJson(const std::filesystem::path& outputPath); + + // Reads a combined JSON file and writes each entry back as an individual + // .datacontainer file in ASSETS_FOLDER. Existing files are overwritten. + static bool importFromJson(const std::filesystem::path& inputPath); +}; diff --git a/Engine_Master_UPC/Engine.vcxproj b/Engine_Master_UPC/Engine.vcxproj index a84a8e98..18008c57 100644 --- a/Engine_Master_UPC/Engine.vcxproj +++ b/Engine_Master_UPC/Engine.vcxproj @@ -305,6 +305,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + @@ -651,6 +652,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + diff --git a/Engine_Master_UPC/Engine.vcxproj.filters b/Engine_Master_UPC/Engine.vcxproj.filters index ad592ef0..a56c0e79 100644 --- a/Engine_Master_UPC/Engine.vcxproj.filters +++ b/Engine_Master_UPC/Engine.vcxproj.filters @@ -482,6 +482,11 @@ NavMesh + + + + + @@ -1113,7 +1118,6 @@ Haptics - Core @@ -1155,6 +1159,15 @@ NavMesh + + + + + + + + + @@ -1365,6 +1378,7 @@ Editor\imgui\NodeEditor + @@ -1409,5 +1423,6 @@ D3D12\Shaders + \ No newline at end of file diff --git a/Engine_Master_UPC/ModuleEditor.cpp b/Engine_Master_UPC/ModuleEditor.cpp index 8352f3cd..40c09025 100644 --- a/Engine_Master_UPC/ModuleEditor.cpp +++ b/Engine_Master_UPC/ModuleEditor.cpp @@ -32,6 +32,8 @@ #include "DataContainerFactory.h" #include "ContentRegistry.h" #include "CommandCreateDataContainer.h" +#include "DataContainerExporter.h" +#include "FileDialog.h" #include @@ -185,6 +187,28 @@ void ModuleEditor::update() handleKeyboardShortcuts(); } } + + if (!m_dcDialogRunning.load()) + { + std::optional result; + { + std::lock_guard lock(m_dcDialogMutex); + if (m_dcDialogResult.has_value()) + { + result = std::move(m_dcDialogResult); + m_dcDialogResult.reset(); + } + } + + if (result.has_value()) + { + if (m_dcDialogMode == 1) + DataContainerExporter::exportToJson(result.value()); + else if (m_dcDialogMode == 2) + DataContainerExporter::importFromJson(result.value()); + m_dcDialogMode = 0; + } + } } void ModuleEditor::render() @@ -359,6 +383,36 @@ void ModuleEditor::mainMenuBar() ImGui::TextDisabled("No asset types registered"); } + ImGui::Separator(); + if (ImGui::MenuItem("Export Data Assets...")) + { + if (!m_dcDialogRunning.load()) + { + m_dcDialogMode = 1; + m_dcDialogRunning.store(true); + { std::lock_guard lock(m_dcDialogMutex); m_dcDialogResult.reset(); } + std::thread([this]() { + auto result = saveAs("JSON Files (*.json)\0*.json\0", "json", "Export Data Assets", ASSETS_FOLDER); + { std::lock_guard lock(m_dcDialogMutex); m_dcDialogResult = std::move(result); } + m_dcDialogRunning.store(false); + }).detach(); + } + } + if (ImGui::MenuItem("Import Data Assets...")) + { + if (!m_dcDialogRunning.load()) + { + m_dcDialogMode = 2; + m_dcDialogRunning.store(true); + { std::lock_guard lock(m_dcDialogMutex); m_dcDialogResult.reset(); } + std::thread([this]() { + auto result = open("JSON Files (*.json)\0*.json\0", "Import Data Assets", ASSETS_FOLDER); + { std::lock_guard lock(m_dcDialogMutex); m_dcDialogResult = std::move(result); } + m_dcDialogRunning.store(false); + }).detach(); + } + } + ImGui::EndMenu(); } diff --git a/Engine_Master_UPC/ModuleEditor.h b/Engine_Master_UPC/ModuleEditor.h index 07ab0973..692b4083 100644 --- a/Engine_Master_UPC/ModuleEditor.h +++ b/Engine_Master_UPC/ModuleEditor.h @@ -8,6 +8,7 @@ #include #include #include +#include "mutex" class ModuleGameView; class WindowSceneEditor; @@ -184,4 +185,10 @@ class ModuleEditor : public Module // Prefab editing PrefabEditSession m_prefabSession; bool m_pendingExitPrefab = false; + + // Async file dialog for DataContainer export/import + std::atomic m_dcDialogRunning = false; + std::mutex m_dcDialogMutex; + std::optional m_dcDialogResult; + int m_dcDialogMode = 0; // 1=export, 2=import }; \ No newline at end of file From 33cfcd26f351c5c148df6c14dd9882fd1dd3134c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Fri, 22 May 2026 11:40:06 +0200 Subject: [PATCH 07/34] Drag and drop of the config working --- Engine_Master_UPC/Engine.vcxproj | 2 + Engine_Master_UPC/ScriptAPI.h | 3 +- Engine_Master_UPC/ScriptDataContainerRef.h | 12 ++ .../ScriptFieldHandlerRegistry.h | 3 +- .../ScriptFieldHandler_DataContainerRef.cpp | 136 ++++++++++++++++++ Engine_Master_UPC/ScriptFieldInfo.h | 3 +- Engine_Master_UPC/ScriptFieldMacros.h | 5 +- GameScripts/Bound.cpp | 13 ++ GameScripts/Bound.h | 4 + 9 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 Engine_Master_UPC/ScriptDataContainerRef.h create mode 100644 Engine_Master_UPC/ScriptFieldHandler_DataContainerRef.cpp diff --git a/Engine_Master_UPC/Engine.vcxproj b/Engine_Master_UPC/Engine.vcxproj index 18008c57..b70e7414 100644 --- a/Engine_Master_UPC/Engine.vcxproj +++ b/Engine_Master_UPC/Engine.vcxproj @@ -373,6 +373,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + @@ -692,6 +693,7 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + diff --git a/Engine_Master_UPC/ScriptAPI.h b/Engine_Master_UPC/ScriptAPI.h index 5f1dca41..ee7f3b0b 100644 --- a/Engine_Master_UPC/ScriptAPI.h +++ b/Engine_Master_UPC/ScriptAPI.h @@ -8,4 +8,5 @@ #include "ScriptFieldInfo.h" #include "ScriptFieldMacros.h" -#include "ScriptComponentRef.h" \ No newline at end of file +#include "ScriptComponentRef.h" +#include "ScriptDataContainerRef.h" \ No newline at end of file diff --git a/Engine_Master_UPC/ScriptDataContainerRef.h b/Engine_Master_UPC/ScriptDataContainerRef.h new file mode 100644 index 00000000..54bf7f8a --- /dev/null +++ b/Engine_Master_UPC/ScriptDataContainerRef.h @@ -0,0 +1,12 @@ +#pragma once + +#include "UID.h" +#include + +class DataContainer; + +struct ScriptDataContainerRef +{ + UID uid = INVALID_UID; + std::shared_ptr dataContainer; +}; diff --git a/Engine_Master_UPC/ScriptFieldHandlerRegistry.h b/Engine_Master_UPC/ScriptFieldHandlerRegistry.h index a08ded2a..1579ca5f 100644 --- a/Engine_Master_UPC/ScriptFieldHandlerRegistry.h +++ b/Engine_Master_UPC/ScriptFieldHandlerRegistry.h @@ -12,4 +12,5 @@ ENGINE_API const ScriptFieldHandler* getVec3FieldHandler(); ENGINE_API const ScriptFieldHandler* getEnumIntFieldHandler(); ENGINE_API const ScriptFieldHandler* getComponentRefFieldHandler(); ENGINE_API const ScriptFieldHandler* getComponentRefListFieldHandler(); -ENGINE_API const ScriptFieldHandler* getStringFieldHandler(); \ No newline at end of file +ENGINE_API const ScriptFieldHandler* getStringFieldHandler(); +ENGINE_API const ScriptFieldHandler* getDataContainerRefFieldHandler(); \ No newline at end of file diff --git a/Engine_Master_UPC/ScriptFieldHandler_DataContainerRef.cpp b/Engine_Master_UPC/ScriptFieldHandler_DataContainerRef.cpp new file mode 100644 index 00000000..490fb096 --- /dev/null +++ b/Engine_Master_UPC/ScriptFieldHandler_DataContainerRef.cpp @@ -0,0 +1,136 @@ +#include "Globals.h" + +#include "ScriptFieldInfo.h" +#include "ScriptFieldHandler.h" +#include "ScriptFieldHandlerRegistry.h" +#include "Script.h" +#include "ScriptDataContainerRef.h" + +#include "Application.h" +#include "ModuleAssets.h" +#include "DataContainer.h" +#include "AssetReference.h" +#include "AssetType.h" + +namespace +{ + void drawDataContainerRefFieldUi(const ScriptFieldInfo& field, void* data, Script& script, ScriptComponent&) + { + ScriptDataContainerRef* ref = reinterpret_cast(data); + + ImGui::Text("%s", field.name); + ImGui::SameLine(); + + if (ref->dataContainer != nullptr) + { + ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s", ref->dataContainer->getDisplayTypeName()); + } + else + { + ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "None"); + } + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ASSET")) + { + UID droppedUid = *static_cast(payload->Data); + AssetReference* assetRef = app->getModuleAssets()->findReference(droppedUid); + + if (assetRef != nullptr && assetRef->m_type == AssetType::DATA_CONTAINER) + { + auto asset = app->getModuleAssets()->load(*assetRef); + if (asset) + { + ref->uid = droppedUid; + ref->dataContainer = asset; + script.onFieldEdited(field); + } + delete assetRef; + } + else + { + delete assetRef; + } + } + + ImGui::EndDragDropTarget(); + } + + ImGui::SameLine(); + + std::string clearLabel = std::string("Clear###") + field.name; + if (ImGui::Button(clearLabel.c_str())) + { + ref->uid = INVALID_UID; + ref->dataContainer = nullptr; + script.onFieldEdited(field); + } + } + + void serializeDataContainerRefField(const ScriptFieldInfo& field, const void* data, rapidjson::Value& outFieldsJson, rapidjson::Document& domTree) + { + const ScriptDataContainerRef* ref = reinterpret_cast(data); + + rapidjson::Value key(field.name, domTree.GetAllocator()); + outFieldsJson.AddMember(key, static_cast(ref->uid), domTree.GetAllocator()); + } + + void deserializeDataContainerRefField(const ScriptFieldInfo&, void* data, const rapidjson::Value& valueJson) + { + if (!valueJson.IsUint64()) + { + return; + } + + ScriptDataContainerRef* ref = reinterpret_cast(data); + + ref->uid = static_cast(valueJson.GetUint64()); + ref->dataContainer = nullptr; + } + + void cloneDataContainerRefField(const ScriptFieldInfo&, const void* sourceData, void* targetData) + { + const ScriptDataContainerRef* sourceRef = reinterpret_cast(sourceData); + + ScriptDataContainerRef* targetRef = reinterpret_cast(targetData); + + targetRef->uid = sourceRef->uid; + targetRef->dataContainer = nullptr; + } + + void fixReferencesDataContainerRefField(const ScriptFieldInfo&, void* data, const SceneReferenceResolver&) + { + ScriptDataContainerRef* ref = reinterpret_cast(data); + + ref->dataContainer = nullptr; + + if (!isValidUID(ref->uid)) + { + return; + } + + AssetReference assetRef; + assetRef.m_uid = ref->uid; + assetRef.m_type = AssetType::DATA_CONTAINER; + + auto asset = app->getModuleAssets()->load(assetRef); + if (asset) + { + ref->dataContainer = asset; + } + } + + const ScriptFieldHandler dataContainerRefFieldHandler = { + &drawDataContainerRefFieldUi, + &serializeDataContainerRefField, + &deserializeDataContainerRefField, + &cloneDataContainerRefField, + &fixReferencesDataContainerRefField + }; +} + +const ScriptFieldHandler* getDataContainerRefFieldHandler() +{ + return &dataContainerRefFieldHandler; +} diff --git a/Engine_Master_UPC/ScriptFieldInfo.h b/Engine_Master_UPC/ScriptFieldInfo.h index c424386c..cf5ce093 100644 --- a/Engine_Master_UPC/ScriptFieldInfo.h +++ b/Engine_Master_UPC/ScriptFieldInfo.h @@ -13,7 +13,8 @@ enum class ScriptFieldType EnumInt, ComponentRef, ComponentRefList, - String + String, + DataContainerRef }; struct ScriptFieldFloatInfo diff --git a/Engine_Master_UPC/ScriptFieldMacros.h b/Engine_Master_UPC/ScriptFieldMacros.h index db414917..4da5f4f9 100644 --- a/Engine_Master_UPC/ScriptFieldMacros.h +++ b/Engine_Master_UPC/ScriptFieldMacros.h @@ -53,4 +53,7 @@ { DisplayName, ScriptFieldType::ComponentRef, offsetof(ThisScript, MemberName), getComponentRefFieldHandler(), {}, {}, { ComponentTypeValue } } #define SERIALIZED_COMPONENT_REF_LIST(MemberName, DisplayName, ComponentTypeValue) \ - { DisplayName, ScriptFieldType::ComponentRefList, offsetof(ThisScript, MemberName), getComponentRefListFieldHandler(), {}, {}, { ComponentTypeValue } } \ No newline at end of file + { DisplayName, ScriptFieldType::ComponentRefList, offsetof(ThisScript, MemberName), getComponentRefListFieldHandler(), {}, {}, { ComponentTypeValue } } + +#define SERIALIZED_DATACONTAINER_REF(MemberName, DisplayName) \ + { DisplayName, ScriptFieldType::DataContainerRef, offsetof(ThisScript, MemberName), getDataContainerRefFieldHandler() } \ No newline at end of file diff --git a/GameScripts/Bound.cpp b/GameScripts/Bound.cpp index c60e0b81..74d53b0d 100644 --- a/GameScripts/Bound.cpp +++ b/GameScripts/Bound.cpp @@ -1,11 +1,13 @@ #include "pch.h" #include "Bound.h" +#include "BoundConfig.h" #include "Damageable.h" IMPLEMENT_SCRIPT_FIELDS(Bound, SERIALIZED_COMPONENT_REF(m_firstTarget, "Player 1 Transform", ComponentType::TRANSFORM), SERIALIZED_COMPONENT_REF(m_secondTarget, "Player 2 Transform", ComponentType::TRANSFORM), SERIALIZED_COMPONENT_REF(m_BoundUI, "Bound UI", ComponentType::TRANSFORM), + SERIALIZED_DATACONTAINER_REF(m_config, "Config"), SERIALIZED_FLOAT(m_minDistance, "Min Distance", 0.0f, 0.0f, 0.1f), SERIALIZED_FLOAT(m_distanceDamage, "Damage Distance", 0.0f, 0.0f, 0.1f), SERIALIZED_FLOAT(m_distanceInstaKill, "InstaKill Distance", 0.0f, 0.0f, 0.1f), @@ -21,6 +23,17 @@ Bound::Bound(GameObject* owner) : Script(owner) void Bound::Start() { + if (m_config.dataContainer) + { + BoundConfig* cfg = static_cast(m_config.dataContainer.get()); + m_minDistance = cfg->m_minDistance; + m_distanceDamage = cfg->m_distanceDamage; + m_distanceInstaKill = cfg->m_distanceInstaKill; + m_radiusThreshold = cfg->m_radiusThreshold; + baseDamage = cfg->m_baseDamage; + maxDamage = cfg->m_maxDamage; + } + GameObject* player1 = ComponentAPI::getOwner(m_firstTarget.getReferencedComponent()); GameObject* player2 = ComponentAPI::getOwner(m_secondTarget.getReferencedComponent()); diff --git a/GameScripts/Bound.h b/GameScripts/Bound.h index 2e949c43..aa23d69a 100644 --- a/GameScripts/Bound.h +++ b/GameScripts/Bound.h @@ -1,9 +1,11 @@ #pragma once #include "ScriptAPI.h" +#include "ScriptDataContainerRef.h" class Transform; class Damageable; +class BoundConfig; class Bound : public Script { @@ -28,6 +30,8 @@ class Bound : public Script Damageable* m_firstDamageable = nullptr; Damageable* m_secondDamageable = nullptr; + ScriptDataContainerRef m_config; + float m_minDistance = 70.0f; float m_distanceDamage = 80.0f; float m_distanceInstaKill = 100.0f; From 64b721568b6f23339ca160f9e3a2e13b0158b970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Mon, 25 May 2026 13:15:31 +0200 Subject: [PATCH 08/34] Solving merge conflicts --- Engine_Master_UPC/ScriptFieldInfo.h | 2 +- Engine_Master_UPC/ScriptFieldMacros.h | 1 - Engine_Master_UPC/Texture.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Engine_Master_UPC/ScriptFieldInfo.h b/Engine_Master_UPC/ScriptFieldInfo.h index 8e6f5610..ee3fc893 100644 --- a/Engine_Master_UPC/ScriptFieldInfo.h +++ b/Engine_Master_UPC/ScriptFieldInfo.h @@ -14,7 +14,7 @@ enum class ScriptFieldType ComponentRef, ComponentRefList, String, - DataContainerRef + DataContainerRef, List }; diff --git a/Engine_Master_UPC/ScriptFieldMacros.h b/Engine_Master_UPC/ScriptFieldMacros.h index fe2786c2..e41e105d 100644 --- a/Engine_Master_UPC/ScriptFieldMacros.h +++ b/Engine_Master_UPC/ScriptFieldMacros.h @@ -58,7 +58,6 @@ #define SERIALIZED_DATACONTAINER_REF(MemberName, DisplayName) \ { DisplayName, ScriptFieldType::DataContainerRef, offsetof(ThisScript, MemberName), getDataContainerRefFieldHandler() } - { DisplayName, ScriptFieldType::ComponentRefList, offsetof(ThisScript, MemberName), getComponentRefListFieldHandler(), {}, {}, { ComponentTypeValue } } // Vector (std::vector) field macros diff --git a/Engine_Master_UPC/Texture.h b/Engine_Master_UPC/Texture.h index e40bfa20..fcb4e552 100644 --- a/Engine_Master_UPC/Texture.h +++ b/Engine_Master_UPC/Texture.h @@ -112,7 +112,7 @@ class Texture : public Resource, public ICacheable DescriptorHandle m_dsv{}; DescriptorHandle m_uav[MAX_MIPS]{}; - DescriptorHeapBlock* m_contiguousRTV; + DescriptorHeapBlock* m_contiguousRTV = nullptr; }; From 396636e5de04be9aa7b33c99eb99256fa7631ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Sun, 31 May 2026 23:56:19 +0200 Subject: [PATCH 09/34] .gitignore update --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 37115e50..6d13cea3 100644 --- a/.gitignore +++ b/.gitignore @@ -433,3 +433,4 @@ FodyWeavers.xsd *.msm *.msp /Engine_Master_UPC/3rdParty/DirectXTK12/x64/Debug/DirectXTK12.vcxproj.FileListAbsolute.txt +/Engine_Master_UPC/migrate_assets From b83a30057f454b292845b4af03a779f13b4018c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Barbar=C3=A0?= Date: Mon, 1 Jun 2026 00:32:15 +0200 Subject: [PATCH 10/34] Created Generic Factory for both Scripts and Data Containers. --- Engine_Master_UPC/AnimationComponent.cpp | 4 +- Engine_Master_UPC/Application.cpp | 2 +- .../CommandCreateDataContainer.cpp | 7 +- Engine_Master_UPC/DataContainer.cpp | 61 +++++++++++- Engine_Master_UPC/DataContainer.h | 6 ++ Engine_Master_UPC/DataContainerAPI.h | 26 +---- Engine_Master_UPC/DataContainerAutoRegister.h | 27 ------ Engine_Master_UPC/DataContainerCreator.h | 8 -- Engine_Master_UPC/DataContainerFactory.cpp | 50 ---------- Engine_Master_UPC/DataContainerFactory.h | 18 ---- Engine_Master_UPC/DataContainerFieldMacros.h | 11 +++ Engine_Master_UPC/DataContainerRegistry.h | 11 --- Engine_Master_UPC/Engine.vcxproj | 11 +-- Engine_Master_UPC/Engine.vcxproj.filters | 26 +++-- Engine_Master_UPC/EngineAPI.cpp | 11 +-- Engine_Master_UPC/EngineAPI.h | 7 +- Engine_Master_UPC/GenericTypeFactory.h | 94 +++++++++++++++++++ Engine_Master_UPC/ImporterDataContainer.cpp | 4 - Engine_Master_UPC/ModuleAssets.cpp | 4 +- Engine_Master_UPC/ModuleAssets.h | 2 +- Engine_Master_UPC/ModuleEditor.cpp | 2 +- Engine_Master_UPC/ScriptAPI.h | 2 +- Engine_Master_UPC/ScriptAutoRegister.h | 27 ------ Engine_Master_UPC/ScriptComponent.cpp | 4 +- Engine_Master_UPC/ScriptCreator.h | 8 -- Engine_Master_UPC/ScriptFactory.cpp | 45 --------- Engine_Master_UPC/ScriptFactory.h | 15 --- Engine_Master_UPC/ScriptRegistry.h | 10 -- Engine_Master_UPC/WindowFileDialog.cpp | 2 +- GameScripts/BoundConfig.cpp | 67 ++----------- GameScripts/BoundConfig.h | 4 - 31 files changed, 215 insertions(+), 361 deletions(-) delete mode 100644 Engine_Master_UPC/DataContainerAutoRegister.h delete mode 100644 Engine_Master_UPC/DataContainerCreator.h delete mode 100644 Engine_Master_UPC/DataContainerFactory.cpp delete mode 100644 Engine_Master_UPC/DataContainerFactory.h create mode 100644 Engine_Master_UPC/DataContainerFieldMacros.h delete mode 100644 Engine_Master_UPC/DataContainerRegistry.h create mode 100644 Engine_Master_UPC/GenericTypeFactory.h delete mode 100644 Engine_Master_UPC/ScriptAutoRegister.h delete mode 100644 Engine_Master_UPC/ScriptCreator.h delete mode 100644 Engine_Master_UPC/ScriptFactory.cpp delete mode 100644 Engine_Master_UPC/ScriptFactory.h delete mode 100644 Engine_Master_UPC/ScriptRegistry.h diff --git a/Engine_Master_UPC/AnimationComponent.cpp b/Engine_Master_UPC/AnimationComponent.cpp index 149fafef..22827ffa 100644 --- a/Engine_Master_UPC/AnimationComponent.cpp +++ b/Engine_Master_UPC/AnimationComponent.cpp @@ -12,7 +12,7 @@ #include "GameObject.h" #include "Transform.h" #include "StateMachineScript.h" -#include "ScriptFactory.h" +#include "GenericTypeFactory.h" #include "Script.h" #include "ScriptComponentRef.h" #include "ModuleScene.h" @@ -1533,7 +1533,7 @@ StateMachineScript* AnimationComponent::createStateBehaviourIfNeeded(const Anima return existing; } - std::unique_ptr