2026-02-13 19:15:05 +01:00
|
|
|
#include "CScene.hpp"
|
2026-03-14 20:24:17 +01:00
|
|
|
#include "../Entity/CEntity.hpp"
|
|
|
|
|
#include "../Component/Graphics/CRenderer.hpp"
|
|
|
|
|
#include "../Component/Meta/CMetaData.hpp"
|
|
|
|
|
#include "../Component/Geometry/CTransform.hpp"
|
|
|
|
|
#include "../Component/Camera/CCamera.hpp"
|
2026-04-17 21:00:35 +02:00
|
|
|
#include "../Systems/Graphics/API/GraphicsAPI.hpp"
|
|
|
|
|
#include "../../Utils/JsonParser/Identifier.hpp"
|
|
|
|
|
#include "../../Utils/Factory/CEntityFactory.hpp"
|
|
|
|
|
#include "../../Utils/Factory/ComponentFactory.hpp"
|
2026-02-13 19:15:05 +01:00
|
|
|
|
2026-04-25 00:45:43 +02:00
|
|
|
#include "Core/Component/Light/CLight.hpp"
|
2026-04-17 21:00:35 +02:00
|
|
|
#include "glm/ext/vector_float3.hpp"
|
|
|
|
|
#include "glm/gtc/type_ptr.hpp"
|
|
|
|
|
#include "nlohmann/json_fwd.hpp"
|
|
|
|
|
|
|
|
|
|
#include <fstream>
|
2026-03-14 20:24:17 +01:00
|
|
|
#include <memory>
|
2026-04-17 21:00:35 +02:00
|
|
|
#include <optional>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <vector>
|
2026-04-25 00:45:43 +02:00
|
|
|
#include "../Systems/Graphics/Data/Light/CLightsBuffer.hpp"
|
2026-02-13 19:15:05 +01:00
|
|
|
namespace CosmicCore {
|
|
|
|
|
|
|
|
|
|
CScene::CScene(std::string name) : CSerializable(),
|
2026-04-24 22:51:54 +02:00
|
|
|
m_name(std::move(name)),
|
|
|
|
|
m_tangibleWorld(this),
|
|
|
|
|
m_audioWorld(this),
|
|
|
|
|
m_scriptWorld(this)
|
2026-03-22 00:28:03 +01:00
|
|
|
{
|
|
|
|
|
m_tangibleWorld.initWorld();
|
2026-04-17 21:00:35 +02:00
|
|
|
m_audioWorld.initWorld();
|
|
|
|
|
m_scriptWorld.initWorld();
|
2026-04-25 00:45:43 +02:00
|
|
|
m_lightsBuffer.init();
|
2026-02-13 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string CScene::getName(void) const {
|
|
|
|
|
return m_name;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-22 00:28:03 +01:00
|
|
|
CScene::~CScene()
|
|
|
|
|
{
|
|
|
|
|
m_tangibleWorld.destroy();
|
2026-04-17 21:00:35 +02:00
|
|
|
m_audioWorld.destroy();
|
|
|
|
|
m_scriptWorld.destroy();
|
2026-03-22 00:28:03 +01:00
|
|
|
}
|
2026-03-14 20:24:17 +01:00
|
|
|
|
2026-03-22 00:28:03 +01:00
|
|
|
CEntity CScene::createEntity(){
|
2026-03-14 20:24:17 +01:00
|
|
|
auto handle = m_ecManager.registry.create();
|
|
|
|
|
CEntity handler(m_ecManager, handle, this);
|
|
|
|
|
return handler;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 19:15:05 +01:00
|
|
|
unsigned int CScene::getNumEntity(void) const {
|
2026-03-14 20:24:17 +01:00
|
|
|
return m_ecManager().view<CMetaData>()->size();
|
2026-02-13 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CScene::removeEntity(unsigned int index, bool destroy)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 00:45:43 +02:00
|
|
|
void CScene::collectLights(vk::raii::CommandBuffer& cmd, uint32_t frameIndex) {
|
|
|
|
|
auto& registry = m_ecManager.registry;
|
|
|
|
|
auto view = registry.view<CLight, CTransform>();
|
|
|
|
|
|
|
|
|
|
SLightsUBOData lightsData{};
|
|
|
|
|
|
|
|
|
|
for (auto entity : view) {
|
|
|
|
|
if (lightsData.lightCount >= MAX_LIGHTS) break;
|
|
|
|
|
|
|
|
|
|
auto& light = registry.get<CLight>(entity);
|
|
|
|
|
auto& transform = registry.get<CTransform>(entity);
|
|
|
|
|
|
|
|
|
|
SLightData data{};
|
|
|
|
|
glm::vec3 pos = transform.getCenter();
|
|
|
|
|
glm::vec3 dir = transform.getOrientation() * glm::vec3(0, -1, 0);
|
|
|
|
|
|
|
|
|
|
data.position = {pos.x, pos.y, pos.z, (float)light.getType()};
|
|
|
|
|
data.direction = {dir.x, dir.y, dir.z, light.getRange()};
|
|
|
|
|
data.color = {light.getColor().x, light.getColor().y,
|
|
|
|
|
light.getColor().z, light.getIntensity()};
|
|
|
|
|
data.innerCosAngle = glm::cos(glm::radians(light.getInnerAngle()));
|
|
|
|
|
data.outerCosAngle = glm::cos(glm::radians(light.getOuterAngle()));
|
|
|
|
|
data.attenuation = light.getAttenuation();
|
|
|
|
|
|
|
|
|
|
lightsData.lights[lightsData.lightCount++] = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// upload dans le SSBO
|
|
|
|
|
m_lightsBuffer.update(frameIndex, lightsData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-03-14 20:24:17 +01:00
|
|
|
void CScene::render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
|
|
|
|
|
auto entities = m_ecManager.registry.view<CRenderer, CTransform>();
|
|
|
|
|
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
|
|
|
|
auto cam = m_ecManager.registry.view<CCamera, CTransform>();
|
|
|
|
|
auto& camera = m_ecManager.registry.get<CCamera>(cam.front());
|
|
|
|
|
auto& transform = m_ecManager.registry.get<CTransform>(cam.front());
|
|
|
|
|
|
2026-04-25 00:45:43 +02:00
|
|
|
collectLights(cmd, frameIndex);
|
|
|
|
|
|
2026-03-14 20:24:17 +01:00
|
|
|
camera.updateUniformBuffer(frameIndex, transform);
|
|
|
|
|
|
|
|
|
|
cmd.bindDescriptorSets(
|
|
|
|
|
vk::PipelineBindPoint::eGraphics,
|
|
|
|
|
api->getDefaultPipelineLayout(), // layout du pipeline
|
|
|
|
|
0,
|
|
|
|
|
*camera.getDescriptorSet(frameIndex),
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-25 00:45:43 +02:00
|
|
|
//bind lumières (set 3)
|
|
|
|
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
|
|
|
|
api->getDefaultPipelineLayout(), 3,
|
|
|
|
|
*m_lightsBuffer.getDescriptorSet(frameIndex), {});
|
|
|
|
|
|
|
|
|
|
|
2026-03-14 20:24:17 +01:00
|
|
|
for (auto& entity : entities) {
|
|
|
|
|
auto model = m_ecManager.registry.get<CRenderer>(entity).getModel();
|
|
|
|
|
auto& transform = m_ecManager.registry.get<CTransform>(entity);
|
|
|
|
|
|
|
|
|
|
transform.updateUniformBuffer(frameIndex);
|
|
|
|
|
//trier meshes par matérial ?
|
|
|
|
|
|
|
|
|
|
// bind transform UBO (set = 1)
|
|
|
|
|
cmd.bindDescriptorSets(
|
|
|
|
|
vk::PipelineBindPoint::eGraphics,
|
|
|
|
|
api->getDefaultPipelineLayout(), // layout du pipeline
|
|
|
|
|
1, // set = 1
|
|
|
|
|
*transform.getDescriptorSet(frameIndex),
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-17 21:00:35 +02:00
|
|
|
for (auto& mm : model->getMeshMaterials()) {
|
2026-03-14 20:24:17 +01:00
|
|
|
// ne rebind le pipeline que si le material change
|
|
|
|
|
//if (mesh.getMaterial() != boundMaterial) {
|
|
|
|
|
//boundMaterial = mesh.getMaterial();
|
|
|
|
|
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics,
|
2026-04-17 21:00:35 +02:00
|
|
|
*mm.material->getPipeline());
|
2026-03-14 20:24:17 +01:00
|
|
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
2026-04-17 21:00:35 +02:00
|
|
|
*mm.material->getPipelineLayout(),
|
2026-03-14 20:24:17 +01:00
|
|
|
2,
|
2026-04-17 21:00:35 +02:00
|
|
|
*mm.material->getDescriptorSet(frameIndex),
|
2026-03-14 20:24:17 +01:00
|
|
|
{});
|
|
|
|
|
//}
|
|
|
|
|
|
2026-04-17 21:00:35 +02:00
|
|
|
cmd.bindVertexBuffers(0, vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getVertexOffset());
|
|
|
|
|
cmd.bindIndexBuffer(vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getIndexOffset(), vk::IndexType::eUint32);
|
|
|
|
|
cmd.drawIndexed(mm.mesh->getIndexCount(), 1, 0, 0, 0);
|
2026-03-14 20:24:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
2026-02-13 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nlohmann::json CScene::to_json()
|
|
|
|
|
{
|
|
|
|
|
return nlohmann::json();
|
|
|
|
|
}
|
2026-04-17 21:00:35 +02:00
|
|
|
|
|
|
|
|
std::unique_ptr<CScene> CScene::load(const std::string &path)
|
|
|
|
|
{
|
|
|
|
|
std::ifstream file(path);
|
|
|
|
|
nlohmann::json sceneJson = nlohmann::json::parse(file);
|
|
|
|
|
if(CosmicUtils::JsonValidator::validate(sceneJson))
|
|
|
|
|
{
|
|
|
|
|
std::string sceneName = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Name)];
|
|
|
|
|
|
|
|
|
|
std::unordered_map<unsigned int, CEntity> idToHandle;
|
|
|
|
|
std::unordered_map<unsigned int, unsigned int> idToParent;
|
|
|
|
|
std::unordered_map<unsigned int, std::vector<unsigned int>> idToChildren;
|
|
|
|
|
|
|
|
|
|
//TODO add descritpion to members
|
|
|
|
|
std::string sceneDescription = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Description)];
|
|
|
|
|
auto scene = std::make_unique<CScene>(sceneName);
|
|
|
|
|
nlohmann::json& entities = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Entities)];
|
|
|
|
|
for(auto& entity : entities.items())
|
|
|
|
|
{
|
|
|
|
|
nlohmann::json& entityObj = entity.value();
|
|
|
|
|
auto ref = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Ref)].get<unsigned int>();
|
|
|
|
|
std::optional<unsigned int> parent = !entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Parent)].is_null() ? std::optional<unsigned int>(entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Parent)].get<unsigned int>()) : std::nullopt;
|
|
|
|
|
auto children = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Children)].get<std::vector<unsigned int>>();
|
|
|
|
|
|
|
|
|
|
nlohmann::json& components = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Components)];
|
|
|
|
|
nlohmann::json& transform = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Transform)];
|
|
|
|
|
nlohmann::json& camera = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Camera)];
|
|
|
|
|
nlohmann::json& collider = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Collider)];
|
|
|
|
|
nlohmann::json& rigidbody = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Rigidbody)];
|
|
|
|
|
nlohmann::json& renderer = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Renderer)];
|
|
|
|
|
nlohmann::json& speaker = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Speaker)];
|
|
|
|
|
nlohmann::json& script = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Script)];
|
2026-04-25 00:45:43 +02:00
|
|
|
nlohmann::json& light = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Light)];
|
2026-04-17 21:00:35 +02:00
|
|
|
|
|
|
|
|
auto trConfig(!transform.is_null() ? std::optional<CosmicUtils::ComponentFactory::TransformConfig>({
|
|
|
|
|
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Position)].get<std::vector<float>>().data()),
|
|
|
|
|
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Rotation)].get<std::vector<float>>().data()),
|
|
|
|
|
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Scale)].get<std::vector<float>>().data())
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
|
|
|
|
auto camConfig(!camera.is_null() ? std::optional<CosmicUtils::ComponentFactory::CameraConfig>({
|
|
|
|
|
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Fov)].get<float>(),
|
|
|
|
|
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Near)].get<float>(),
|
|
|
|
|
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Far)].get<float>()
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
|
|
|
|
auto colliderConfig(!collider.is_null() ? std::optional<CosmicUtils::ComponentFactory::ColliderConfig>({
|
|
|
|
|
static_cast<EColliderType>(collider[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Collider_Type)].get<int>()),
|
|
|
|
|
glm::vec3(),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
|
|
|
|
auto rigidbodyConfig(!rigidbody.is_null() ? std::optional<CosmicUtils::ComponentFactory::RigidBodyConfig>({
|
|
|
|
|
static_cast<EBodyType>(rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Type)].get<int>()),
|
|
|
|
|
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Mass)].get<float>(),
|
|
|
|
|
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Friction)].get<float>(),
|
|
|
|
|
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Restitution)].get<float>()
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
|
|
|
|
auto rendererConfig(!renderer.is_null() ? std::optional<CosmicUtils::ComponentFactory::RendererConfig>({
|
|
|
|
|
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Model)].get<std::string>(),
|
|
|
|
|
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Shader)].get<std::string>(),
|
|
|
|
|
!renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Albedo)].is_null() ? std::optional<std::string>(renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Albedo)].get<std::string>()) : std::nullopt,
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
|
|
|
|
auto scriptConfig(!script.is_null() ? std::optional<CosmicUtils::ComponentFactory::ScriptConfig>({
|
|
|
|
|
script.get<std::vector<std::string>>()
|
|
|
|
|
}): std::nullopt);
|
|
|
|
|
|
|
|
|
|
std::optional<CosmicUtils::ComponentFactory::SpeakerConfig> speakerConfig = std::nullopt;
|
|
|
|
|
if(!speaker.is_null())
|
|
|
|
|
{
|
|
|
|
|
if(!speaker[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Clips)].empty())
|
|
|
|
|
{
|
|
|
|
|
speakerConfig = std::optional<CosmicUtils::ComponentFactory::SpeakerConfig>(CosmicUtils::ComponentFactory::SpeakerConfig());
|
|
|
|
|
for(auto clipConf : speaker[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Clips)])
|
|
|
|
|
{
|
|
|
|
|
CosmicUtils::ComponentFactory::SpeakerConfig::SoundClipConfig conf
|
|
|
|
|
{
|
|
|
|
|
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Path)].get<std::string>(),
|
|
|
|
|
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Gain)].get<float>(),
|
|
|
|
|
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Pitch)].get<float>(),
|
|
|
|
|
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Loop)].get<bool>(),
|
|
|
|
|
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Spatial)].get<bool>()
|
|
|
|
|
};
|
|
|
|
|
speakerConfig->clips.push_back(conf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 00:45:43 +02:00
|
|
|
auto lightConfig(!light.is_null() ? std::optional<CosmicUtils::ComponentFactory::LightConfig>(
|
|
|
|
|
{
|
|
|
|
|
static_cast<ELightType>(light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_Type)].get<unsigned int>()),
|
|
|
|
|
glm::make_vec3(light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_Color)].get<std::vector<float>>().data()),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_Intensity)].get<float>(),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_Range)].get<float>(),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_Attenuation)].get<float>(),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_InnerAngle)].get<float>(),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_OuterAngle)].get<float>(),
|
|
|
|
|
light[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Light_CastShadow)].get<bool>()
|
|
|
|
|
}) : std::nullopt);
|
|
|
|
|
|
2026-04-17 21:00:35 +02:00
|
|
|
CosmicUtils::CEntityFactory::EntityConfig config = {
|
|
|
|
|
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Name)],
|
|
|
|
|
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Description)],
|
|
|
|
|
trConfig,
|
|
|
|
|
camConfig,
|
|
|
|
|
rendererConfig,
|
|
|
|
|
colliderConfig,
|
|
|
|
|
rigidbodyConfig,
|
|
|
|
|
speakerConfig,
|
2026-04-25 00:45:43 +02:00
|
|
|
scriptConfig,
|
|
|
|
|
lightConfig
|
2026-04-17 21:00:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto entityHandle = CosmicUtils::CEntityFactory::create(scene.get(), config);
|
|
|
|
|
idToHandle.emplace(std::make_pair(ref, entityHandle));
|
|
|
|
|
if(parent.has_value())
|
|
|
|
|
idToParent[ref] = parent.value();
|
|
|
|
|
|
|
|
|
|
for(auto i : children)
|
|
|
|
|
{
|
|
|
|
|
idToChildren[ref].push_back(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Connect entities to relationships
|
|
|
|
|
for(auto& [entityNb, handle]: idToHandle)
|
|
|
|
|
{
|
|
|
|
|
CosmicUtils::ComponentFactory::RelationshipConfig cnf;
|
|
|
|
|
if(idToParent.find(entityNb) != idToParent.end())
|
|
|
|
|
{
|
|
|
|
|
cnf.parent = std::optional<EntityId>(idToHandle.at(idToParent.at(entityNb)).getHandle());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cnf.parent = std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto& child : idToChildren[entityNb])
|
|
|
|
|
{
|
|
|
|
|
cnf.children.push_back(idToHandle.at(child).getHandle());
|
|
|
|
|
}
|
|
|
|
|
CosmicUtils::ComponentFactory::addRelationship(handle, cnf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return scene;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CScene::save(CScene *scene, const std::string &path)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CScene::save(const std::string& path)
|
|
|
|
|
{
|
|
|
|
|
save(this, path);
|
|
|
|
|
}
|
2026-02-13 19:15:05 +01:00
|
|
|
}
|