From eea7b4c06769f0ea90fdbc16cc42b9a1940180b4 Mon Sep 17 00:00:00 2001 From: CatChow0 <thetrueshibadoggo@gmail.com> Date: Tue, 18 Mar 2025 22:43:23 +0100 Subject: [PATCH] Major Update - V9.0.0 [FEAT] : + Add Save and Load system for scene but only for kobject --- .../.idea/workspace.xml | 44 +++--- enginecustom/assets/empty.ker | 1 + enginecustom/assets/imgui.ini | 29 ++++ enginecustom/assets/scene.ker | 1 + .../src/inc/system/applicationclass.h | 6 +- enginecustom/src/inc/system/object.h | 4 + enginecustom/src/src/system/Systemclass.cpp | 67 ++++++++- .../src/src/system/applicationclass.cpp | 138 ++++++++++++++---- enginecustom/src/src/system/imguiManager.cpp | 3 +- enginecustom/src/src/system/object.cpp | 2 +- 10 files changed, 240 insertions(+), 55 deletions(-) create mode 100644 enginecustom/assets/empty.ker create mode 100644 enginecustom/assets/imgui.ini create mode 100644 enginecustom/assets/scene.ker diff --git a/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml b/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml index fc53c90..472357b 100644 --- a/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml +++ b/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml @@ -5,10 +5,13 @@ </component> <component name="ChangeListManager"> <list default="true" id="e81d6e08-efc7-40a0-909d-ec4943d948e9" name="Changes" comment=""> - <change beforePath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/projectSettingsUpdater.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/projectSettingsUpdater.xml" 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/src/inc/system/applicationclass.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/applicationclass.h" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/object.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/object.h" afterDir="false" /> <change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/Systemclass.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/Systemclass.cpp" afterDir="false" /> <change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/applicationclass.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/applicationclass.cpp" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/imguiManager.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/imguiManager.cpp" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/object.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/object.cpp" afterDir="false" /> </list> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" /> @@ -41,25 +44,25 @@ <option name="hideEmptyMiddlePackages" value="true" /> <option name="showLibraryContents" value="true" /> </component> - <component name="PropertiesComponent"><![CDATA[{ - "keyToString": { - "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", - "C++ Project.enginecustom.executor": "Run", - "C/C++ Project.enginecustom.executor": "Debug", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.git.unshallow": "true", - "SHARE_PROJECT_CONFIGURATION_FILES": "true", - "git-widget-placeholder": "main", - "ignore.virus.scanning.warn.message": "true", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "preferences.pluginManager", - "vue.rearranger.settings.migration": "true" + <component name="PropertiesComponent">{ + "keyToString": { + "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", + "C++ Project.enginecustom.executor": "Run", + "C/C++ Project.enginecustom.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "SHARE_PROJECT_CONFIGURATION_FILES": "true", + "git-widget-placeholder": "main", + "ignore.virus.scanning.warn.message": "true", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "preferences.pluginManager", + "vue.rearranger.settings.migration": "true" } -}]]></component> +}</component> <component name="RunManager" selected="C/C++ Project.enginecustom"> <configuration name="KhaoticDemo" type="CppProject" factoryName="C++ Project"> <configuration_1 setup="1"> @@ -134,6 +137,9 @@ <workItem from="1742207107802" duration="5340000" /> <workItem from="1742228751298" duration="38000" /> <workItem from="1742228870107" duration="1198000" /> + <workItem from="1742314944369" duration="79000" /> + <workItem from="1742318452773" duration="2258000" /> + <workItem from="1742331065936" duration="3030000" /> </task> <task id="LOCAL-00001" summary="Minor update - viewport window tweak"> <option name="closed" value="true" /> diff --git a/enginecustom/assets/empty.ker b/enginecustom/assets/empty.ker new file mode 100644 index 0000000..05d9672 --- /dev/null +++ b/enginecustom/assets/empty.ker @@ -0,0 +1 @@ +0 isosphere 0 10 0 1 1 1 F:\Github_Repo\khaotic-engine-Reborn\enginecustom\assets\Model\OBJ\isosphere.obj diff --git a/enginecustom/assets/imgui.ini b/enginecustom/assets/imgui.ini new file mode 100644 index 0000000..fd23f2c --- /dev/null +++ b/enginecustom/assets/imgui.ini @@ -0,0 +1,29 @@ +[Window][DockSpace] +Pos=0,0 +Size=1584,861 +Collapsed=0 + +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Khaotic Engine] +Pos=1223,27 +Size=353,826 +Collapsed=0 +DockId=0x00000002,0 + +[Window][Objects] +Pos=8,27 +Size=345,826 +Collapsed=0 +DockId=0x00000003,0 + +[Docking][Data] +DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=8,27 Size=1568,826 Split=X + DockNode ID=0x00000003 Parent=0xCCBD8CF7 SizeRef=345,826 Selected=0x031DC75C + DockNode ID=0x00000004 Parent=0xCCBD8CF7 SizeRef=1221,826 Split=X + DockNode ID=0x00000001 Parent=0x00000004 SizeRef=866,826 CentralNode=1 + DockNode ID=0x00000002 Parent=0x00000004 SizeRef=353,826 Selected=0x9F035453 + diff --git a/enginecustom/assets/scene.ker b/enginecustom/assets/scene.ker new file mode 100644 index 0000000..c083e14 --- /dev/null +++ b/enginecustom/assets/scene.ker @@ -0,0 +1 @@ +1 isosphere 0 14.4537 0 1 1 1 F:\Github_Repo\khaotic-engine-Reborn\enginecustom\assets\Model\OBJ\isosphere.obj diff --git a/enginecustom/src/inc/system/applicationclass.h b/enginecustom/src/inc/system/applicationclass.h index bfec01c..7f2b5fa 100644 --- a/enginecustom/src/inc/system/applicationclass.h +++ b/enginecustom/src/inc/system/applicationclass.h @@ -93,7 +93,7 @@ public: std::vector<Object*> GetCubes() const { return m_cubes; }; std::vector<Object*> GetTerrainCubes() const { return m_terrainChunk; }; std::vector<Object*> GetKobjects() const { return m_object; }; - void AddKobject(WCHAR* filepath); + void AddKobject(std::wstring& filepath); void SetPath(WCHAR* path) { m_path = path; }; void SetWFolder(std::filesystem::path WFolder) { m_WFolder = WFolder; }; @@ -152,6 +152,9 @@ public: void LoadScene(); void SetScenePath(std::string path) { m_scenePath = path; }; + std::wstring GetScenePath(); + + std::string ConvertWStringToString(const std::wstring& wstr); private: bool Render(float, float, float, float, float); @@ -167,6 +170,7 @@ private: void ConstructSkybox(); // Construct the skybox void UpdateSkyboxPosition(); // Update the skybox position bool RenderSkybox(XMMATRIX view, XMMATRIX projection); // Render the skybox + public : std::vector<ID3D11ShaderResourceView*> textures; diff --git a/enginecustom/src/inc/system/object.h b/enginecustom/src/inc/system/object.h index 42c2c14..6349489 100644 --- a/enginecustom/src/inc/system/object.h +++ b/enginecustom/src/inc/system/object.h @@ -86,6 +86,9 @@ public: float GetBoundingRadius() const; + void SetModelPath(std::wstring& path) { m_modelPath = path; } + std::wstring& GetModelPath() { return m_modelPath; } + public : bool m_demoSpinning = false; XMVECTOR m_previousPosition; @@ -110,4 +113,5 @@ private: ShaderType m_activeShader = LIGHTING; float m_boundingRadius; + std::wstring m_modelPath; }; diff --git a/enginecustom/src/src/system/Systemclass.cpp b/enginecustom/src/src/system/Systemclass.cpp index 949808b..8fda0f2 100644 --- a/enginecustom/src/src/system/Systemclass.cpp +++ b/enginecustom/src/src/system/Systemclass.cpp @@ -149,11 +149,68 @@ void SystemClass::Run() done = false; - // Ask For the scene file - GetScenePath(); - - m_Application->LoadScene(); + // Ask if the user wants to load a scene or create a new one + int result_scene = MessageBox(NULL, L"Do you want to load a saved scene?", L"Load Scene", MB_YESNO | MB_ICONQUESTION); + if (result_scene == IDYES) + { + std::wstring scenePath = m_Application->GetScenePath(); + if (!scenePath.empty()) + { + m_Application->SetScenePath(m_Application->ConvertWStringToString(scenePath)); + m_Application->LoadScene(); + } + } + else + { + OPENFILENAME ofn; + wchar_t szFile[260] = L""; + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = m_hwnd; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile); + // Allow multiple extensions + ofn.lpstrFilter = L"Ker Scene (*.ker)\0*.ker\0All Files (*.*)\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; + if (GetSaveFileName(&ofn) == TRUE) + { + std::filesystem::path filepath = ofn.lpstrFile; + std::string path = filepath.string(); + + // Add the selected extension if not already present + switch (ofn.nFilterIndex) + { + case 1: + if (filepath.extension() != L".ker") + path += ".ker"; + break; + case 2: + if (filepath.extension() != L".txt") + path += ".txt"; + break; + } + + m_Application->SetScenePath(path); + // Create a new scene file + std::ofstream outFile(path); + if (outFile.is_open()) + { + // Initialize the new scene file with default content if needed + outFile.close(); + Logger::Get().Log("New scene file created successfully", __FILE__, __LINE__, Logger::LogLevel::Info); + } + else + { + Logger::Get().Log("Failed to create new scene file", __FILE__, __LINE__, Logger::LogLevel::Error); + } + } + } + while (!done) { // Handle the windows messages. @@ -305,7 +362,7 @@ LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam if (extension == L"txt" || extension == L"kobj") { // Handle dropped files with valid extensions std::wcout << L"File dropped: " << filePath << std::endl; - m_Application->AddKobject(filePath); + m_Application->AddKobject(fileName); } else { // Handle files with invalid extensions (optional) diff --git a/enginecustom/src/src/system/applicationclass.cpp b/enginecustom/src/src/system/applicationclass.cpp index 651d8b8..01ce2ea 100644 --- a/enginecustom/src/src/system/applicationclass.cpp +++ b/enginecustom/src/src/system/applicationclass.cpp @@ -1429,9 +1429,8 @@ void ApplicationClass::GenerateTerrain() } -void ApplicationClass::AddKobject(WCHAR* filepath) +void ApplicationClass::AddKobject(std::wstring& filepath) { - Logger::Get().Log("Adding object", __FILE__, __LINE__); char modelFilename[128]; @@ -1442,7 +1441,7 @@ void ApplicationClass::AddKobject(WCHAR* filepath) string filename = p.stem().string(); size_t convertedChars = 0; - wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), filepath, _TRUNCATE); + wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), filepath.c_str(), _TRUNCATE); filesystem::current_path(m_WFolder); @@ -1460,23 +1459,7 @@ void ApplicationClass::AddKobject(WCHAR* filepath) result = DirectX::CreateWICTextureFromFile(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), textureFilename.c_str(), nullptr, &texture); if (FAILED(result)) { - // Utiliser _com_error pour obtenir des informations d�taill�es sur l'erreur - _com_error err(result); - LPCTSTR errMsg = err.ErrorMessage(); - - //convertie errMessage en std::wstring - std::wstring ws(errMsg); - std::string str(ws.begin(), ws.end()); - - // Log the current working directory - std::filesystem::path cwd = std::filesystem::current_path(); - Logger::Get().Log("Current working directory: " + cwd.string(), __FILE__, __LINE__, Logger::LogLevel::Error); - - Logger::Get().Log("Failed to load texture: " + std::string(textureFilename.begin(), textureFilename.end()) + - "\nError: " + std::to_string(result) + - "\nDescription: " + str, - __FILE__, __LINE__, Logger::LogLevel::Error); - return; // Assurez-vous de retourner false ou de g�rer l'erreur de mani�re appropri�e + // Handle error } textures.push_back(texture); } @@ -1487,12 +1470,12 @@ void ApplicationClass::AddKobject(WCHAR* filepath) newObject->SetTranslateMatrix(XMMatrixTranslation(0.0f, 50.0f, 0.0f)); newObject->SetName(filename); newObject->SetId(m_ObjectId); + newObject->SetModelPath(filepath); // Store the path as std::wstring m_ObjectId++; m_object.push_back(newObject); - // V�rifiez que l'objet a bien re�u les textures if (newObject->GetTexture(0) == nullptr) { @@ -2245,18 +2228,117 @@ bool ApplicationClass::RenderSkybox(XMMATRIX view, XMMATRIX projection) { return true; } +std::string ApplicationClass::ConvertWStringToString(const std::wstring& wstr) +{ + if (wstr.empty()) return std::string(); + + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); + std::string str(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size_needed, NULL, NULL); + return str; +} + void ApplicationClass::SaveScene() { - + if (m_scenePath.empty()) + { + Logger::Get().Log("Scene path is empty. Cannot save scene.", __FILE__, __LINE__, Logger::LogLevel::Error); + return; + } + + std::ofstream outFile(m_scenePath); + if (!outFile.is_open()) + { + Logger::Get().Log("Failed to open file for saving scene", __FILE__, __LINE__, Logger::LogLevel::Error); + return; + } + + for (const auto& object : m_object) + { + XMFLOAT3 position, scale; + XMStoreFloat3(&position, object->GetPosition()); + XMStoreFloat3(&scale, object->GetScale()); + outFile << object->GetId() << " " << object->GetName() << " " + << position.x << " " << position.y << " " << position.z << " " + << scale.x << " " << scale.y << " " << scale.z << " " + << ConvertWStringToString(object->GetModelPath()) << std::endl; // Convert model path to std::string + } + + outFile.close(); + Logger::Get().Log("Scene saved successfully", __FILE__, __LINE__, Logger::LogLevel::Info); } void ApplicationClass::LoadScene() { - // Read the file and load the scene - // File is in a custom format - // every object is defined by a line with the following format: - // m_id,m_scaleMatrix,m_rotateMatrix,m_translateMatrix,m_srMatrix, - // m_worldMatrix,m_mass,m_isPhysicsEnabled,m_name,m_type,m_activeShader, - // m_boundingRadius,m_texture[n],m_demoSpinning + std::wstring scenePath = GetScenePath(); + if (!scenePath.empty()) + { + SetScenePath(ConvertWStringToString(scenePath)); + } + + if (m_scenePath.empty()) + { + Logger::Get().Log("Scene path is empty. Cannot load scene.", __FILE__, __LINE__, Logger::LogLevel::Error); + return; + } + + std::ifstream inFile(m_scenePath); + if (!inFile.is_open()) + { + Logger::Get().Log("Failed to open file for loading scene", __FILE__, __LINE__, Logger::LogLevel::Error); + return; + } + + m_object.clear(); + + int id; + std::string name; + float posX, posY, posZ; + float scaleX, scaleY, scaleZ; + std::string modelPath; + + while (inFile >> id >> name >> posX >> posY >> posZ >> scaleX >> scaleY >> scaleZ >> modelPath) + { + int size_needed = MultiByteToWideChar(CP_UTF8, 0, modelPath.c_str(), (int)modelPath.size(), NULL, 0); + std::wstring wModelPath(size_needed, 0); + MultiByteToWideChar(CP_UTF8, 0, modelPath.c_str(), (int)modelPath.size(), &wModelPath[0], size_needed); + + AddKobject(wModelPath); + + Object* newObject = m_object.back(); + newObject->SetId(id); + newObject->SetName(name); + newObject->SetPosition(XMVectorSet(posX, posY, posZ, 0.0f)); + newObject->SetScale(XMVectorSet(scaleX, scaleY, scaleZ, 0.0f)); + } + + inFile.close(); + Logger::Get().Log("Scene loaded successfully", __FILE__, __LINE__, Logger::LogLevel::Info); +} + +std::wstring ApplicationClass::GetScenePath() +{ + OPENFILENAME ofn; + wchar_t szFile[260]; + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = m_hwnd; + ofn.lpstrFile = szFile; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFilter = L"Ker Scene\0*.ker\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + if (GetOpenFileName(&ofn) == TRUE) + { + std::filesystem::path filepath = ofn.lpstrFile; + return filepath.wstring(); + } + return L""; } \ No newline at end of file diff --git a/enginecustom/src/src/system/imguiManager.cpp b/enginecustom/src/src/system/imguiManager.cpp index 5c168f0..5436f19 100644 --- a/enginecustom/src/src/system/imguiManager.cpp +++ b/enginecustom/src/src/system/imguiManager.cpp @@ -171,7 +171,8 @@ void imguiManager::WidgetAddObject(ApplicationClass* app) if (GetOpenFileName(&ofn)) { - app->AddKobject(ofn.lpstrFile); + std::wstring wstr(ofn.lpstrFile); + app->AddKobject(wstr); } } diff --git a/enginecustom/src/src/system/object.cpp b/enginecustom/src/src/system/object.cpp index 095a4ec..87ea35a 100644 --- a/enginecustom/src/src/system/object.cpp +++ b/enginecustom/src/src/system/object.cpp @@ -1,6 +1,6 @@ #include "object.h" -Object::Object() : ModelClass() +Object::Object()// Initialize the reference here { m_scaleMatrix = XMMatrixIdentity(); m_rotateMatrix = XMMatrixIdentity();