Minor - Implements component serialization - V12.9.0

Adds serialization and deserialization functionality to the ECS component system.

This allows components to be saved and loaded, enabling scene persistence.
The IdentityComponent is updated to support serialization/deserialization.
The scene saving logic in scene_manager is updated to serialize components instead of hardcoded values.
This commit is contained in:
2025-09-06 14:18:28 +02:00
parent ccd0d045f9
commit 55e561fd14
6 changed files with 190 additions and 111 deletions

View File

@@ -5,16 +5,11 @@
</component>
<component name="ChangeListManager">
<list default="true" id="e81d6e08-efc7-40a0-909d-ec4943d948e9" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/Logger.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/Logger.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/Skybox.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/Skybox.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/camera_class.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/camera_class.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/d_3d_class.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/d_3d_class.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/display_plane_class.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/display_plane_class.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/fps_limiter.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/fps_limiter.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/frustum.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/frustum.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/frustumclass.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/frustumclass.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/imguiManager.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/imguiManager.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/scene_manager.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/scene_manager.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/imgui.ini" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/imgui.ini" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/component.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/component.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/identity_component.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/identity_component.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/scene_manager.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/scene_manager.cpp" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@@ -81,7 +76,7 @@
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.environmentSetup&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;MonitoringCountersPageId&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
@@ -242,6 +237,10 @@
<workItem from="1753700140931" duration="918000" />
<workItem from="1753701507863" duration="7153000" />
<workItem from="1753713925469" duration="1739000" />
<workItem from="1754572996727" duration="224000" />
<workItem from="1755617169013" duration="222000" />
<workItem from="1757101936080" duration="185000" />
<workItem from="1757158576637" duration="2501000" />
</task>
<task id="LOCAL-00001" summary="Minor update - viewport window tweak">
<option name="closed" value="true" />

View File

@@ -22,13 +22,13 @@ DockId=0x00000009,0
[Window][Objects]
Pos=0,19
Size=234,609
Size=234,842
Collapsed=0
DockId=0x0000000B,0
[Window][Terrain]
Pos=236,19
Size=266,609
Size=266,842
Collapsed=0
DockId=0x00000007,0
@@ -45,15 +45,15 @@ Collapsed=0
DockId=0x0000000B,1
[Window][Engine Settings]
Pos=1267,462
Size=317,166
Pos=1267,631
Size=317,230
Collapsed=0
DockId=0x00000006,0
[Docking][Data]
DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=0,19 Size=1584,842 Split=Y
DockNode ID=0x00000003 Parent=0xCCBD8CF7 SizeRef=1584,609 Split=X
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=234,842 Selected=0x321620B2
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=234,842 Selected=0x031DC75C
DockNode ID=0x0000000C Parent=0x00000003 SizeRef=1348,842 Split=X
DockNode ID=0x00000007 Parent=0x0000000C SizeRef=266,842 Selected=0x393905AB
DockNode ID=0x00000008 Parent=0x0000000C SizeRef=1316,842 Split=X

View File

@@ -33,8 +33,19 @@ public:
*/
virtual void Update(float deltaTime) {}
// virtual std::string Serialize() {}
// virtual void Deserialize(const std::string& data) {}
/**
* Serialize the component to a string (for debugging or saving).
* @return A string representation of the component.
*/
virtual std::string Serialize() const { return ""; }
/**
* Deserialize the component from a string (for loading).
* @param data The string data to deserialize from.
* @return True if deserialization was successful, otherwise false.
*/
virtual bool Deserialize(const std::string& data) { return false;}
};
/**

View File

@@ -92,6 +92,52 @@ public:
return ObjectType::Unknown;
}
/**
* Serialize the component to a string.
* Format: "id:name:type"
* @return A string representation of the component.
*/
std::string Serialize() const override
{
std::stringstream ss;
ss << m_id << ":" << m_name << ":" << ObjectTypeToString(m_type);
return ss.str();
}
/**
* Deserialize the component from a string.
* Expected format: "id:name:type"
* @param data The string data to deserialize from.
* @return True if deserialization was successful, otherwise false.
*/
bool Deserialize(const std::string& data) override
{
std::stringstream ss(data);
std::string segment;
std::vector<std::string> segments;
while (std::getline(ss, segment, ':'))
{
segments.push_back(segment);
}
if (segments.empty()) return false;
if (segments.size() != 3) return false;
try
{
m_id = std::stoi(segments[0]);
m_name = segments[1];
m_type = StringToObjectType(segments[2]);
return true;
} catch (const std::exception&)
{
return false;
}
}
private:
int m_id; // ID unique de l'objet
std::string m_name; // Nom de l'objet

View File

@@ -124,6 +124,14 @@ public:
}
}
/**
* Get all components of the entity.
* @return A constant reference to the map of components.
*/
const std::unordered_map<ComponentTypeID, ComponentPtr>& GetAllComponents() const {
return m_Components;
}
private:
/**

View File

@@ -310,106 +310,121 @@ bool scene_manager::save_scene() {
return false;
}
for (const auto& object : entity_) {
XMFLOAT3 position, scale, rotation;
int id = 0;
int mass = 0;
float boundingRadius = 0;
std::string name = "NONE";
std::string shaderType = "NONE";
std::string objectType = "NONE";
std::wstring model_path = L"";
bool physics_enabled = false;
outFile << entity_.size() << std::endl;
auto transform = object->GetComponent<ecs::TransformComponent>();
if (transform) {
// convert XMVECTOR to XMFLOAT3
XMStoreFloat3(&position, transform->GetPosition());
XMStoreFloat3(&rotation, transform->GetRotation());
XMStoreFloat3(&scale, transform->GetScale());
}
for (const auto& entity : entity_)
{
const auto& components = entity->GetAllComponents();
outFile << components.size() << std::endl;
auto identity = object->GetComponent<ecs::IdentityComponent>();
if (identity) {
id = identity->GetId();
name = identity->GetName();
objectType = identity->ObjectTypeToString(identity->GetType());
}
auto model_path_component = object->GetComponent<ecs::ModelPathComponent>();
if (model_path_component) {
model_path = model_path_component->GetPath();
}
auto shader = object->GetComponent<ecs::ShaderComponent>();
if (shader)
for (const auto& component : components)
{
shaderType = shader->ShaderTypeToString(shader->GetActiveShader());
outFile << typeid(*component).name() << std::endl;
outFile << component->Serialize() << std::endl;
}
auto physics = object->GetComponent<ecs::PhysicsComponent>();
if (physics) {
physics_enabled = physics->IsPhysicsEnabled();
mass = physics->GetMass();
boundingRadius = physics->GetBoundingRadius();
}
// <20>crire les donn<6E>es de base de l'objet
outFile << id << " "
<< name << " "
<< position.x << " " << position.y << " " << position.z << " "
<< rotation.x << " " << rotation.y << " " << rotation.z << " "
<< scale.x << " " << scale.y << " " << scale.z << " "
<< convert_w_string_to_string(model_path) << " "
<< shaderType << " "
<< boundingRadius << " "
<< objectType << " "
<< mass << " "
<< physics_enabled;
// Sauvegarder les chemins des textures_
// Format: nombre de textures_ diffuses, puis les chemins
// M<>me chose pour les autres types de textures_
auto render = object->GetComponent<ecs::RenderComponent>();
if (render)
{
const auto& model = render->GetModel();
const auto& textureContainer = model->GetTextureContainer();
const auto& diffusePaths = textureContainer.GetPaths(TextureType::Diffuse);
outFile << " " << diffusePaths.size();
for (const auto& path : diffusePaths) {
outFile << " " << convert_w_string_to_string(path);
}
const auto& normalPaths = textureContainer.GetPaths(TextureType::Normal);
outFile << " " << normalPaths.size();
for (const auto& path : normalPaths) {
outFile << " " << convert_w_string_to_string(path);
}
const auto& specularPaths = textureContainer.GetPaths(TextureType::Specular);
outFile << " " << specularPaths.size();
for (const auto& path : specularPaths) {
outFile << " " << convert_w_string_to_string(path);
}
const auto& alphaPaths = textureContainer.GetPaths(TextureType::Alpha);
outFile << " " << alphaPaths.size();
for (const auto& path : alphaPaths) {
outFile << " " << convert_w_string_to_string(path);
}
}
outFile << std::endl;
}
// for (const auto& object : entity_) {
// XMFLOAT3 position, scale, rotation;
// int id = 0;
// int mass = 0;
// float boundingRadius = 0;
// std::string name = "NONE";
// std::string shaderType = "NONE";
// std::string objectType = "NONE";
// std::wstring model_path = L"";
// bool physics_enabled = false;
//
// auto transform = object->GetComponent<ecs::TransformComponent>();
// if (transform) {
// // convert XMVECTOR to XMFLOAT3
// XMStoreFloat3(&position, transform->GetPosition());
// XMStoreFloat3(&rotation, transform->GetRotation());
// XMStoreFloat3(&scale, transform->GetScale());
// }
//
//
// auto identity = object->GetComponent<ecs::IdentityComponent>();
// if (identity) {
//
// id = identity->GetId();
// name = identity->GetName();
// objectType = identity->ObjectTypeToString(identity->GetType());
//
// }
//
// auto model_path_component = object->GetComponent<ecs::ModelPathComponent>();
// if (model_path_component) {
//
// model_path = model_path_component->GetPath();
// }
//
// auto shader = object->GetComponent<ecs::ShaderComponent>();
// if (shader)
// {
// shaderType = shader->ShaderTypeToString(shader->GetActiveShader());
// }
//
// auto physics = object->GetComponent<ecs::PhysicsComponent>();
// if (physics) {
// physics_enabled = physics->IsPhysicsEnabled();
// mass = physics->GetMass();
// boundingRadius = physics->GetBoundingRadius();
// }
//
// // <20>crire les donn<6E>es de base de l'objet
// outFile << id << " "
// << name << " "
// << position.x << " " << position.y << " " << position.z << " "
// << rotation.x << " " << rotation.y << " " << rotation.z << " "
// << scale.x << " " << scale.y << " " << scale.z << " "
// << convert_w_string_to_string(model_path) << " "
// << shaderType << " "
// << boundingRadius << " "
// << objectType << " "
// << mass << " "
// << physics_enabled;
//
// // Sauvegarder les chemins des textures_
// // Format: nombre de textures_ diffuses, puis les chemins
// // M<>me chose pour les autres types de textures_
//
//
// auto render = object->GetComponent<ecs::RenderComponent>();
// if (render)
// {
// const auto& model = render->GetModel();
//
// const auto& textureContainer = model->GetTextureContainer();
//
// const auto& diffusePaths = textureContainer.GetPaths(TextureType::Diffuse);
// outFile << " " << diffusePaths.size();
// for (const auto& path : diffusePaths) {
// outFile << " " << convert_w_string_to_string(path);
// }
//
// const auto& normalPaths = textureContainer.GetPaths(TextureType::Normal);
// outFile << " " << normalPaths.size();
// for (const auto& path : normalPaths) {
// outFile << " " << convert_w_string_to_string(path);
// }
// const auto& specularPaths = textureContainer.GetPaths(TextureType::Specular);
// outFile << " " << specularPaths.size();
// for (const auto& path : specularPaths) {
// outFile << " " << convert_w_string_to_string(path);
// }
// const auto& alphaPaths = textureContainer.GetPaths(TextureType::Alpha);
// outFile << " " << alphaPaths.size();
// for (const auto& path : alphaPaths) {
// outFile << " " << convert_w_string_to_string(path);
// }
// }
//
//
// outFile << std::endl;
// }
outFile.close();
Logger::Get().Log("Scene saved successfully to " + scene_path_, __FILE__, __LINE__, Logger::LogLevel::Info);
return true;