From 763ecff93d9e0a24f243e2ef5830f86be5405e6e Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Tue, 24 Jun 2025 18:58:53 +0200 Subject: [PATCH] Minor - ECS use when loading scene - V12.7.0 --- enginecustom/imgui.ini | 6 +- .../src/inc/system/application_class.h | 3 +- enginecustom/src/src/system/scene_manager.cpp | 203 +++++++++++------- 3 files changed, 135 insertions(+), 77 deletions(-) diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index 69eaeb0..616075e 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Khaotic Engine] Pos=1267,19 -Size=317,609 +Size=317,842 Collapsed=0 DockId=0x00000005,0 @@ -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 diff --git a/enginecustom/src/inc/system/application_class.h b/enginecustom/src/inc/system/application_class.h index ac4d74c..9a7c6ef 100644 --- a/enginecustom/src/inc/system/application_class.h +++ b/enginecustom/src/inc/system/application_class.h @@ -174,6 +174,8 @@ public: fps_class* get_fps() const { return fps_; }; ecs::EntityManager* get_entity_manager() const { return entity_manager_.get(); }; + void update_stats_after_modification(); + std::map>& get_model_cache() { return g_model_cache; } private: bool render(float, float, float, float, float); @@ -188,7 +190,6 @@ private: void update_skybox_position(); void culling_thread_function(); - void update_stats_after_modification(); public : std::vector textures; diff --git a/enginecustom/src/src/system/scene_manager.cpp b/enginecustom/src/src/system/scene_manager.cpp index 9ef6926..75cc199 100644 --- a/enginecustom/src/src/system/scene_manager.cpp +++ b/enginecustom/src/src/system/scene_manager.cpp @@ -67,29 +67,32 @@ bool scene_manager::save_scene_as() { bool scene_manager::load_scene() { Logger::Get().Log("Loading scene from " , __FILE__, __LINE__, Logger::LogLevel::Info); - //object_vec_ = app_->get_kobjects(); // TODO object_id_ = app_->get_object_id(); w_folder_ = app_->get_w_folder(); direct_3d_ = app_->get_direct_3d(); std::wstring scenePath = get_scene_path(); - - if (!scenePath.empty()) - { + if (!scenePath.empty()) { scene_path_ = convert_w_string_to_string(scenePath); } std::ifstream inFile(scene_path_); if (!inFile.is_open()) { - Logger::Get().Log("Failed to open file for loading scene: ", __FILE__, __LINE__, Logger::LogLevel::Error); + Logger::Get().Log("Failed to open file for loading scene: " + scene_path_, __FILE__, __LINE__, Logger::LogLevel::Error); return false; } - object_vec_.clear(); + // Réinitialiser l'ID d'objet le plus élevé object_id_ = 0; + + // Récupérer l'EntityManager pour créer de nouvelles entités + auto entity_manager = app_->get_entity_manager(); + + // Supprimer toutes les entités existantes + entity_manager->Clear(); - // Sauvegarder le répertoire de travail actuel - std::wstring currentDirectory = w_folder_; + // Sauvegarder le répertoire de travail actuel + std::wstring currentDirectory = w_folder_; std::string line; while (std::getline(inFile, line)) { @@ -104,47 +107,61 @@ bool scene_manager::load_scene() { float mass; bool physicsEnabled; - // Lire les données de base de l'objet + // Lire les données de base de l'entité iss >> id >> name >> position.x >> position.y >> position.z >> rotation.x >> rotation.y >> rotation.z - >> scale.x >> scale.y >> scale.z - >> modelPath >> shaderTypeStr + >> scale.x >> scale.y >> scale.z; + + // Lire le chemin du modèle - vérifier s'il est vide + iss >> modelPath; + + // Si le chemin du modèle est vide ou commence par une lettre majuscule (probablement un type de shader), + // c'est qu'il a été omis - utilisez une valeur par défaut + if (modelPath.empty() || (modelPath[0] >= 'A' && modelPath[0] <= 'Z')) { + // Reculer le curseur de lecture pour lire le type de shader à la place + iss.seekg(-static_cast(modelPath.length()), std::ios::cur); + modelPath = "assets/Model/TXT/cube.txt"; // Valeur par défaut + } + + iss >> shaderTypeStr >> boundingRadius >> objectTypeStr >> mass >> physicsEnabled; if (iss.fail()) { - Logger::Get().Log("Failed to parse object data", __FILE__, __LINE__, Logger::LogLevel::Error); + Logger::Get().Log("Failed to parse entity data: " + line, __FILE__, __LINE__, Logger::LogLevel::Error); continue; } - // Créer un nouvel objet - object* newObject = new object(); + // Mettre à jour l'ID d'objet le plus élevé si nécessaire + if (id >= object_id_) { + object_id_ = id + 1; + } // Convertir le chemin du modèle en wstring std::wstring wModelPath(modelPath.begin(), modelPath.end()); - // Vérifier si le chemin est relatif (ne commence pas par un disque comme C:) - if (modelPath.length() > 1 && modelPath[1] != ':') { - // C'est un chemin relatif, préfixer avec le répertoire de travail - if (currentDirectory.back() != L'/' && currentDirectory.back() != L'\\') { - // Ajouter un séparateur si nécessaire - wModelPath = currentDirectory + L"\\" + wModelPath; - } else { - wModelPath = currentDirectory + wModelPath; - } - } + // Vérifier si le chemin est relatif + if (modelPath != "NoModel" && modelPath.length() > 1 && modelPath[1] != ':') { + // C'est un chemin relatif, préfixer avec le répertoire de travail + if (currentDirectory.back() != L'/' && currentDirectory.back() != L'\\') { + // Ajouter un séparateur si nécessaire + wModelPath = currentDirectory + L"\\" + wModelPath; + } else { + wModelPath = currentDirectory + wModelPath; + } + } - // Créer le conteneur de textures_ pour stocker les chemins + // Créer le conteneur de textures pour stocker les chemins TextureContainer objectTextures; - // IMPORTANT: Vider les conteneurs de chemins de textures_ + // Vider les conteneurs de chemins de textures objectTextures.diffusePaths.clear(); objectTextures.normalPaths.clear(); objectTextures.specularPaths.clear(); objectTextures.alphaPaths.clear(); - // Lire les chemins des textures_ diffuses + // Lire les chemins des textures diffuses int diffuseTextureCount; iss >> diffuseTextureCount; for (int i = 0; i < diffuseTextureCount; i++) { @@ -154,7 +171,7 @@ bool scene_manager::load_scene() { objectTextures.diffusePaths.push_back(wTexturePath); } - // Lire les chemins des textures_ normales + // Lire les chemins des textures normales int normalTextureCount; iss >> normalTextureCount; for (int i = 0; i < normalTextureCount; i++) { @@ -164,7 +181,7 @@ bool scene_manager::load_scene() { objectTextures.normalPaths.push_back(wTexturePath); } - // Lire les chemins des textures_ spéculaires + // Lire les chemins des textures spéculaires int specularTextureCount; iss >> specularTextureCount; for (int i = 0; i < specularTextureCount; i++) { @@ -174,7 +191,7 @@ bool scene_manager::load_scene() { objectTextures.specularPaths.push_back(wTexturePath); } - // Lire les chemins des textures_ alpha + // Lire les chemins des textures alpha int alphaTextureCount; iss >> alphaTextureCount; for (int i = 0; i < alphaTextureCount; i++) { @@ -183,62 +200,101 @@ bool scene_manager::load_scene() { std::wstring wTexturePath(texturePath.begin(), texturePath.end()); objectTextures.alphaPaths.push_back(wTexturePath); } - - // preload texture - if (!newObject->get_model()->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), objectTextures)) - { - // Gérer l'erreur - return false; - } - - // Initialiser l'objet avec le modèle et les chemins de textures_ - char modelFilename[256]; - size_t convertedChars = 0; - wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), wModelPath.c_str(), _TRUNCATE); - - Logger::Get().Log("Loading model: " + std::string(modelFilename), __FILE__, __LINE__, Logger::LogLevel::Info); - - // NE PAS charger les textures_ avant initialize - // Laisser la méthode initialize s'en charger à partir des chemins - if (!newObject->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, objectTextures)) { - Logger::Get().Log("Failed to initialize object: " + name, __FILE__, __LINE__, Logger::LogLevel::Error); - delete newObject; + + // Vérifier si on a un modèle à charger + if (modelPath == "NoModel") { + Logger::Get().Log("Skipping entity without model: " + name, __FILE__, __LINE__, Logger::LogLevel::Warning); continue; } - // Définir les propriétés de l'objet - newObject->SetId(id); - newObject->SetName(name); - newObject->SetPosition(XMLoadFloat3(&position)); - newObject->SetRotation(XMLoadFloat3(&rotation)); - newObject->SetScale(XMLoadFloat3(&scale)); - newObject->SetModelPath(wModelPath); - newObject->SetActiveShader(newObject->StringToShaderType(shaderTypeStr)); - newObject->SetBoundingRadius(boundingRadius); - newObject->SetType(newObject->StringToObjectType(objectTypeStr)); - newObject->SetMass(mass); - newObject->SetPhysicsEnabled(physicsEnabled); + // Récupérer le cache de modèles de l'application + auto& modelCache = app_->get_model_cache(); + std::shared_ptr sharedModel; - // Mettre à jour l'ID global si nécessaire - if (id >= object_id_) { - object_id_ = id + 1; - app_->set_object_id(object_id_); + // Vérifier si le modèle existe déjà dans le cache + std::string modelKey = modelPath; + auto it = modelCache.find(modelKey); + if (it != modelCache.end()) { + // Utiliser le modèle existant du cache + Logger::Get().Log("Using cached model for: " + modelKey, __FILE__, __LINE__, Logger::LogLevel::Info); + sharedModel = it->second; + } else { + // Créer un nouveau modèle + char modelFilename[256]; + size_t convertedChars = 0; + wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), wModelPath.c_str(), _TRUNCATE); + + Logger::Get().Log("Loading model: " + std::string(modelFilename), __FILE__, __LINE__, Logger::LogLevel::Info); + + // Créer et initialiser le modèle + auto newModel = std::make_shared(); + + // Précharger les textures + if (!newModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), objectTextures)) { + Logger::Get().Log("Failed to preload textures for: " + name, __FILE__, __LINE__, Logger::LogLevel::Error); + continue; + } + + if (!newModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, objectTextures)) { + Logger::Get().Log("Failed to initialize model: " + name, __FILE__, __LINE__, Logger::LogLevel::Error); + continue; + } + + // Ajouter le modèle au cache + modelCache[modelKey] = newModel; + sharedModel = newModel; } + + // Créer une nouvelle entité avec l'EntityManager + auto entity = entity_manager->CreateEntity(); - object_vec_.push_back(newObject); - Logger::Get().Log("Loaded object: " + name, __FILE__, __LINE__, Logger::LogLevel::Info); + // Ajouter un composant d'identité + auto identityComponent = entity->AddComponent(id); + identityComponent->SetName(name); + identityComponent->SetType(ecs::IdentityComponent::StringToObjectType(objectTypeStr)); + + // Ajouter un composant de transformation + auto transformComponent = entity->AddComponent(); + transformComponent->SetPosition(XMLoadFloat3(&position)); + transformComponent->SetRotation(XMLoadFloat3(&rotation)); + transformComponent->SetScale(XMLoadFloat3(&scale)); + transformComponent->UpdateWorldMatrix(); + + // Ajouter un composant de rendu avec le modèle + auto renderComponent = entity->AddComponent(); + renderComponent->InitializeWithModel(sharedModel); + + // Ajouter un composant de shader + auto shaderComponent = entity->AddComponent(); + shaderComponent->SetActiveShader(ecs::ShaderComponent::StringToShaderType(shaderTypeStr)); + + // Ajouter un composant de chemin de modèle + auto modelPathComponent = entity->AddComponent(); + modelPathComponent->SetPath(wModelPath); + + // Ajouter un composant de physique si nécessaire + auto physicsComponent = entity->AddComponent(); + physicsComponent->Initialize(); + physicsComponent->SetMass(mass); + physicsComponent->SetBoundingRadius(boundingRadius); + physicsComponent->SetPhysicsEnabled(physicsEnabled); + + Logger::Get().Log("Entity loaded: " + name + " with ID: " + std::to_string(id), __FILE__, __LINE__, Logger::LogLevel::Info); } - // pass the vec to the application - //app_->set_kobjects(object_vec_); // TODO + // Mettre à jour l'ID global dans l'application + app_->set_object_id(object_id_); + + // Mettre à jour les statistiques après le chargement + app_->update_stats_after_modification(); - Logger::Get().Log("Scene loaded successfully from ", __FILE__, __LINE__, Logger::LogLevel::Info); + Logger::Get().Log("Scene loaded successfully from " + scene_path_, __FILE__, __LINE__, Logger::LogLevel::Info); return true; } bool scene_manager::save_scene() { - entity_ = app_->get_entity_manager()->GetAllEntities(); + entity_ = app_->get_entity_manager()->GetAllEntities(); if (scene_path_.empty()) { Logger::Get().Log("Scene path is empty. Cannot save scene.", __FILE__, __LINE__, Logger::LogLevel::Error); @@ -392,4 +448,5 @@ std::string scene_manager::convert_w_string_to_string(const std::wstring& wstr) std::string str(size_needed, 0); WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size_needed, NULL, NULL); return str; -} \ No newline at end of file +} +