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">{
+  &quot;keyToString&quot;: {
+    &quot;ASKED_SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
+    &quot;C++ Project.enginecustom.executor&quot;: &quot;Run&quot;,
+    &quot;C/C++ Project.enginecustom.executor&quot;: &quot;Run&quot;,
+    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
+    &quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
+    &quot;git-widget-placeholder&quot;: &quot;main&quot;,
+    &quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
+    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
+    &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
+    &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.pluginManager&quot;,
+    &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
   }
-}]]></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();