diff --git a/Assets/Cube.003.shmesh.shmeta b/Assets/Cube.003.shmesh.shmeta
new file mode 100644
index 00000000..d41be546
--- /dev/null
+++ b/Assets/Cube.003.shmesh.shmeta
@@ -0,0 +1,3 @@
+Name: Cube.003
+ID: 110152941
+Type: 
diff --git a/Assets/Cube.012.shmesh.shmeta b/Assets/Cube.012.shmesh.shmeta
new file mode 100644
index 00000000..d5cd1090
--- /dev/null
+++ b/Assets/Cube.012.shmesh.shmeta
@@ -0,0 +1,3 @@
+Name: Cube.012
+ID: 107348815
+Type: 
diff --git a/Assets/Editor/Layouts/Default.ini b/Assets/Editor/Layouts/Default.ini
index b953b3a5..4ddc46c2 100644
--- a/Assets/Editor/Layouts/Default.ini
+++ b/Assets/Editor/Layouts/Default.ini
@@ -9,8 +9,8 @@ Size=1920,1036
 Collapsed=0
 
 [Window][Hierarchy Panel]
-Pos=0,89
-Size=286,971
+Pos=0,120
+Size=225,940
 Collapsed=0
 DockId=0x00000004,0
 
@@ -20,23 +20,29 @@ Size=400,400
 Collapsed=0
 
 [Window][Inspector]
-Pos=1494,24
-Size=426,1036
+Pos=1686,24
+Size=234,1036
 Collapsed=0
 DockId=0x00000006,0
 
 [Window][Profiler]
 Pos=0,24
-Size=286,63
+Size=225,94
 Collapsed=0
 DockId=0x00000003,0
 
+[Window][Viewport]
+Pos=227,24
+Size=1457,1036
+Collapsed=0
+DockId=0x00000002,0
+
 [Docking][Data]
 DockSpace       ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
-  DockNode      ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1492,1036 Split=X
-    DockNode    ID=0x00000001 Parent=0x00000005 SizeRef=286,1036 Split=Y Selected=0xE096E5AE
-      DockNode  ID=0x00000003 Parent=0x00000001 SizeRef=140,63 Selected=0x1E6EB881
-      DockNode  ID=0x00000004 Parent=0x00000001 SizeRef=140,971 Selected=0xE096E5AE
-    DockNode    ID=0x00000002 Parent=0x00000005 SizeRef=1204,1036 CentralNode=1
-  DockNode      ID=0x00000006 Parent=0xC5C9B8AB SizeRef=426,1036 Selected=0xE7039252
+  DockNode      ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
+    DockNode    ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
+      DockNode  ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
+      DockNode  ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
+    DockNode    ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
+  DockNode      ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252
 
diff --git a/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta
new file mode 100644
index 00000000..f8c267d9
--- /dev/null
+++ b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta
@@ -0,0 +1,3 @@
+Name: RaccoonPreTexturedVer1_Base9
+ID: 91918845
+Type: 
diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp
index d1d3e087..2f37c491 100644
--- a/SHADE_Application/src/Application/SBApplication.cpp
+++ b/SHADE_Application/src/Application/SBApplication.cpp
@@ -104,10 +104,10 @@ namespace Sandbox
 
     //TODO: REMOVE AFTER PRESENTATION
     //SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
-    SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
+    //SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
     //SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
     //SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
-    SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
+    //SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
     //TODO: REMOVE AFTER PRESENTATION
 
 
@@ -125,6 +125,8 @@ namespace Sandbox
     SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
     
     SHFrameRateController::UpdateFRC();
+
+    SHAssetManager::Load();
   }
 
   void SBApplication::Update(void)
@@ -139,17 +141,10 @@ namespace Sandbox
       SHSceneManager::UpdateSceneManager();
 #ifdef SHEDITOR
       if(editor->editorState == SHEditor::State::PLAY)
-#endif
         SHSceneManager::SceneUpdate(0.016f);
-#ifdef SHEDITOR
-      SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
-      if(auto editor = SHSystemManager::GetSystem<SHEditor>())
-      {
-        editor->PollPicking();
-      }
-#else
-      SHSystemManager::RunRoutines(false, 0.016f);
 #endif
+      SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
+      editor->PollPicking();
     }
     // Finish all graphics jobs first
 	  graphicsSystem->AwaitGraphicsExecution();
@@ -165,6 +160,7 @@ namespace Sandbox
 
     SHSceneManager::Exit();
     SHSystemManager::Exit();
+    SHAssetManager::Unload();
   }
 }
 
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h
index 07cebea9..d24b6c02 100644
--- a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h	
+++ b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h	
@@ -9,6 +9,7 @@ namespace SHADE
 	{
 		bool compiled;
 
+		std::string name;
 		uint32_t numBytes;
 		uint32_t width;
 		uint32_t height;
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
index 12b2517e..8026f0e1 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
@@ -16,7 +16,7 @@
 
 #include <fstream>
 
-void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
+std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
 {
 	std::string newPath{ path.string() };
 	newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
@@ -67,4 +67,6 @@ void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPat
 	);
 
 	file.close();
+
+	return newPath;
 }
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.h b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.h
index 6da00525..a8ce67be 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.h
@@ -21,6 +21,6 @@ namespace SHADE
 	{
 	private:
 	public:
-		static void CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
+		static std::string CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
 	};
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
index 3a5fb9ec..4bfa2d9b 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
@@ -142,8 +142,7 @@ namespace SHADE
       SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
     }
 
-    std::string name{ path.filename().string() };
-    name = name.substr(0, name.find_last_of('.'));
+    const std::string name{ path.stem().string() };
 
     file.seekg(0);
 
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
index 3e430aca..a27d63ea 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
@@ -29,8 +29,8 @@ namespace SHADE
 
 		static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
 
-		static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
 	public:
 		static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
+		static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
 	};
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.cpp
index 62af4da6..49de6b5c 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.cpp
@@ -17,7 +17,7 @@
 
 namespace SHADE
 {
-	void SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
+	std::string SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
 	{
 		std::string newPath{ path.string() };
 		newPath = newPath.substr(0, newPath.find_last_of('.'));
@@ -69,5 +69,7 @@ namespace SHADE
 		);
 
 		file.close();
+
+		return newPath;
 	}
 }
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.h b/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.h
index d8685795..52980084 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureCompiler.h
@@ -19,6 +19,6 @@ namespace SHADE
 {
 	struct SHTextureCompiler
 	{
-		static void CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
+		static std::string CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
 	};
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
index 47501d42..5147562a 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
@@ -93,6 +93,7 @@ namespace SHADE
 		std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
 		//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
 
+		asset.name = path.stem().string();
 		asset.compiled = false;
 		asset.numBytes = static_cast<uint32_t>(totalBytes);
 		asset.width = file.GetWidth();
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
index e84fe5cf..eb61ea91 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
@@ -26,8 +26,8 @@ namespace SHADE
 
 
 		static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
-		static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
 	public:
 		static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
+		static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
 	};
 }
diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h
index 8c462af7..61c5879d 100644
--- a/SHADE_Engine/src/Assets/SHAssetMacros.h
+++ b/SHADE_Engine/src/Assets/SHAssetMacros.h
@@ -40,7 +40,7 @@ typedef FMOD::Sound*					SHSound;
 #define ASSET_META_VER "1.0"
 
 // Asset type enum
-enum class AssetType : uint8_t
+enum class AssetType : AssetTypeMeta
 {
 	INVALID = 0,
 	AUDIO = 1,
@@ -57,7 +57,12 @@ enum class AssetType : uint8_t
 };
 
 //Directory
-#define ASSET_ROOT "./Assets/"
+#ifdef _PUBLISH
+#define ASSET_ROOT "Assets"
+#else
+#define ASSET_ROOT "../../Assets"
+#endif
+
 
 // ASSET EXTENSIONS
 #define META_EXTENSION ".shmeta"
diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp
index 430b8c79..aa9772dd 100644
--- a/SHADE_Engine/src/Assets/SHAssetManager.cpp
+++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp
@@ -255,6 +255,26 @@ namespace SHADE
 		return result;
 	}
 
+	SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
+	{
+		if (meshCollection.find(id) == meshCollection.end())
+		{
+			return nullptr;
+		}
+
+		return &meshCollection[id];
+	}
+
+	SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
+	{
+		if (textureCollection.find(id) == textureCollection.end())
+		{
+			return nullptr;
+		}
+
+		return &textureCollection[id];
+	}
+
 	/****************************************************************************
 	 * \param   Path for meta data file
 	 * \param   Path for asset file
@@ -307,12 +327,22 @@ namespace SHADE
 
 		for (auto const& mesh : meshes)
 		{
-			meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh);
+			auto id{ GenerateAssetID(AssetType::MESH) };
+			meshCollection.emplace(id, mesh);
 
+			AssetPath path;
 			if (!mesh.compiled)
 			{
-				SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
+				path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
 			}
+			
+			assetCollection.emplace_back(
+				mesh.header.meshName,
+				id,
+				AssetType::MESH,
+				path,
+				0
+			);
 		}
 	}
 
@@ -322,11 +352,20 @@ namespace SHADE
 
 		SHTextureLoader::LoadImageAsset(asset.path, image);
 
-		textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
-
 		if (!image.compiled)
 		{
-			SHTextureCompiler::CompileTextureBinary(image, asset.path);
+			auto id{ GenerateAssetID(AssetType::TEXTURE) };
+			textureCollection.emplace(id, image);
+
+			auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
+
+			assetCollection.emplace_back(
+				image.name,
+				id,
+				AssetType::TEXTURE,
+				path,
+				0
+			);
 		}
 	}
 
@@ -344,8 +383,24 @@ namespace SHADE
 	****************************************************************************/
 	void SHAssetManager::LoadAllData() noexcept
 	{
+		//TODO Remove when on demand loading is done
 		for (auto const& asset : assetCollection)
 		{
+			switch (asset.type)
+			{
+			case AssetType::MESH:
+				meshCollection.emplace(asset.id, SHMeshAsset());
+				SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
+				break;
+
+			case AssetType::TEXTURE:
+				textureCollection.emplace(asset.id, SHTextureAsset());
+				SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
+				break;
+
+			default:
+				void;
+			}
 		}
 	}
 
@@ -362,40 +417,51 @@ namespace SHADE
 		std::vector<AssetPath> metaFiles;
 		std::vector<AssetPath> AssetFiles;
 
-		//TODO: Write new function for file manager to loop through all files
-		SHFileSystem::StartupFillDirectories(ASSET_ROOT);
-		FolderPointer rootFolder = SHFileSystem::GetRoot();
-
-		for (auto const& meta : metaFiles)
+		for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
 		{
-			for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
-				it != AssetFiles.cend();
-				++it)
+			if (dir.path().extension().string() == META_EXTENSION)
 			{
-				// Asset exists for meta file
-				std::string fileExtCheck{ it->filename().string() };
-				fileExtCheck += META_EXTENSION;
-				if (meta.filename().string() == fileExtCheck)
-				{
-					RegisterAsset(meta, *it);
-					AssetFiles.erase(it);
-					break;
-				}
+				auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
+
+				assetCollection.push_back(meta);
+				assetRegistry.emplace(meta.id, meta);
 			}
 		}
 
+		//TODO: Write new function for file manager to loop through all files
+		//SHFileSystem::StartupFillDirectories(ASSET_ROOT);
+		//FolderPointer rootFolder = SHFileSystem::GetRoot();
+
+		//for (auto const& meta : metaFiles)
+		//{
+		//	for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
+		//		it != AssetFiles.cend();
+		//		++it)
+		//	{
+		//		// Asset exists for meta file
+		//		std::string fileExtCheck{ it->filename().string() };
+		//		fileExtCheck += META_EXTENSION;
+		//		if (meta.filename().string() == fileExtCheck)
+		//		{
+		//			RegisterAsset(meta, *it);
+		//			AssetFiles.erase(it);
+		//			break;
+		//		}
+		//	}
+		//}
+
 		//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
-		for (auto const& file : AssetFiles)
-		{
-			if (IsRecognised(file.extension().string().c_str()))
-			{
-				SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
-			}
-			else
-			{
-				std::cout << "Unsupported File Format: " << file.filename() << "\n";
-			}
-		}
+		//for (auto const& file : AssetFiles)
+		//{
+		//	if (IsRecognised(file.extension().string().c_str()))
+		//	{
+		//		SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
+		//	}
+		//	else
+		//	{
+		//		std::cout << "Unsupported File Format: " << file.filename() << "\n";
+		//	}
+		//}
 	}
 
 	AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h
index 7064d63d..50549e01 100644
--- a/SHADE_Engine/src/Assets/SHAssetManager.h
+++ b/SHADE_Engine/src/Assets/SHAssetManager.h
@@ -75,6 +75,8 @@ namespace SHADE
 		static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
 		static std::vector<SHTextureAsset> GetAllTextures() noexcept;
 
+		static SHMeshAsset const* GetMesh(AssetID id) noexcept;
+		static SHTextureAsset const* GetTexture(AssetID id) noexcept;
 	private:
 		/****************************************************************************
 		 * \brief   Load resource data into memory
diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
index 6554a3e4..442c3d96 100644
--- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
+++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
@@ -72,6 +72,13 @@ namespace SHADE
 		std::string line;
 		SHAsset meta;
 
+		// Get resource name
+		GetFieldValue(metaFile, line);
+		std::stringstream nameStream{ line };
+		AssetName name;
+		nameStream >> name;
+		meta.name = name;
+
 		// Get resource id
 		GetFieldValue(metaFile, line);
 		std::stringstream idStream{ line };
@@ -88,6 +95,8 @@ namespace SHADE
 
 		metaFile.close();
 
+		meta.path = path.parent_path().string() + "/" + path.stem().string();
+
 		return meta;
 	}
 
@@ -103,7 +112,7 @@ namespace SHADE
 		std::string path{ meta.path.string() };
 		path.append(META_EXTENSION);
 
-		std::ofstream metaFile{ path, std::ios_base::out };
+		std::ofstream metaFile{ path, std::ios_base::out | std::ios_base::trunc };
 
 		if (!metaFile.is_open())
 		{
@@ -113,17 +122,17 @@ namespace SHADE
 
 		metaFile << "Name: " << meta.name << "\n";
 		metaFile << "ID: " << meta.id << "\n";
-		metaFile << "Type: " << static_cast<int>(meta.type) << std::endl;
+		metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
 
-		//TODO Add in information that is specific to types like mesh
-		switch(meta.type)
-		{
-		case AssetType::MESH:
-			break;
+		////TODO Add in information that is specific to types like mesh
+		//switch(meta.type)
+		//{
+		//case AssetType::MESH:
+		//	break;
 
-		default:
-			break;
-		}
+		//default:
+		//	break;
+		//}
 
 		metaFile.close();
 	}
diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp
index c2316006..c2666a0d 100644
--- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp
+++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp
@@ -21,6 +21,8 @@
 //#==============================================================#
 #include <imgui.h>
 
+#include "Serialization/SHSerialization.h"
+
 
 namespace SHADE
 {
@@ -181,6 +183,10 @@ namespace SHADE
         editor->selectedEntities.clear();
         editor->selectedEntities.push_back(eid);
       }
+      if(ImGui::Selectable("Copy"))
+      {
+        SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
+      }
       if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
       {
         SHEntityManager::DestroyEntity(eid);
diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp
index 3cb6561d..c33f4fb6 100644
--- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp
+++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp
@@ -17,6 +17,8 @@
 #include <imgui_internal.h>
 #include <rttr/type>
 
+#include "Serialization/SHSerialization.h"
+
 namespace SHADE
 {
   constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@@ -73,7 +75,14 @@ namespace SHADE
       {
         if (ImGui::BeginMenu("File"))
         {
-
+          if(ImGui::Selectable("Save"))
+          {
+            SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
+          }
+          if(ImGui::Selectable("Load"))
+          {
+            SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
+          }
           ImGui::EndMenu();
         }
         if(ImGui::BeginMenu("Edit"))
diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.cpp b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.cpp
index 491c1bc2..edbe0faa 100644
--- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.cpp
+++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.cpp
@@ -54,6 +54,7 @@ namespace SHADE
       windowPos = {wndPos.x, wndPos.y};
       OnPosChange();
     }
+    isWindowHovered = ImGui::IsWindowHovered();
     return result;
   }
 
diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.h
index 3e7a2a5c..f46cd880 100644
--- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.h
+++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindow.h
@@ -24,6 +24,7 @@ namespace SHADE
     virtual void Update();
     virtual void Exit();
     bool isOpen;
+    bool isWindowHovered;
     std::string_view windowName;
   protected:
     virtual bool Begin();
@@ -34,5 +35,6 @@ namespace SHADE
     ImGuiIO& io;
     SHVec2 windowSize;
     SHVec2 windowPos;
+    SHVec2 viewportMousePos;
   };//class SHEditorWindow
 }//namespace SHADE
diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp
index 60c91754..420443ae 100644
--- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp
+++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp
@@ -2,7 +2,11 @@
 #include "SHEditorViewport.h"
 
 #include "ECS_Base/Managers/SHSystemManager.h"
+#include "Editor/SHEditor.hpp"
+#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
 #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
+#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
 
 namespace SHADE
 {
@@ -24,8 +28,27 @@ namespace SHADE
     {
       DrawMenuBar();
       auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
-      //auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
-      //ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
+      auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
+      auto mousePos = ImGui::GetMousePos();
+      auto cursorPos = ImGui::GetCursorScreenPos();
+      viewportMousePos = {mousePos.x - cursorPos.x, mousePos.y - cursorPos.y};
+      gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
+      //if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
+      //{
+      //  auto eid = gfxSystem->GetMousePickSystem ()->GetPickedEntity();
+      //  if(eid != MAX_EID)
+      //  {
+      //    auto editor = SHSystemManager::GetSystem<SHEditor>();
+      //    editor->selectedEntities.clear();
+      //    editor->selectedEntities.push_back(eid);
+      //    if (const auto hierarchyPanel = SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>())
+      //    {
+      //      hierarchyPanel->SetScrollTo(eid);
+      //    }
+      //  }
+      //}
+
+      ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
     }
     ImGui::End();
   }
@@ -39,6 +62,11 @@ namespace SHADE
   {
     SHEditorWindow::OnResize();
     //Get graphics system to resize swapchain image
+    auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
+
+    //auto pos = ImGui::GetCursorPos();
+    //windowCursorPos = {}
+    gfxSystem->PrepareResize(static_cast<uint32_t>(windowSize.x), static_cast<uint32_t>(windowSize.y));
   }
 
   void SHEditorViewport::OnPosChange()
diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp
index e7606337..6b3c3a93 100644
--- a/SHADE_Engine/src/Editor/SHEditor.cpp
+++ b/SHADE_Engine/src/Editor/SHEditor.cpp
@@ -304,10 +304,11 @@ namespace SHADE
     imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
     imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
 
-    auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
+    //auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
+    auto const& renderers = gfxSystem->GetEditorViewport()->GetRenderers();
 
     SHASSERT(!renderers.empty(), "No Renderers available")
-    auto renderGraph = renderers[0]->GetRenderGraph();
+    auto renderGraph = renderers[SHGraphicsConstants::RenderGraphIndices::EDITOR]->GetRenderGraph();
     auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
 
     if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
@@ -336,7 +337,8 @@ namespace SHADE
   {
     if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
     {
-      if (!ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
+      auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
+      if (viewportWindow->isWindowHovered && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
       {
         EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity();
         if(pickedEID == MAX_EID)
diff --git a/SHADE_Engine/src/Editor/SHEditorUI.cpp b/SHADE_Engine/src/Editor/SHEditorUI.cpp
index 65b65827..76f7bac6 100644
--- a/SHADE_Engine/src/Editor/SHEditorUI.cpp
+++ b/SHADE_Engine/src/Editor/SHEditorUI.cpp
@@ -67,6 +67,11 @@ namespace SHADE
     ImGui::Separator();
   }
 
+  bool SHEditorUI::IsItemHovered()
+  {
+    return ImGui::IsItemHovered();
+  }
+
   bool SHEditorUI::BeginMenu(const std::string& label)
   {
 	  return ImGui::BeginMenu(label.data());
@@ -82,6 +87,16 @@ namespace SHADE
     ImGui::EndMenu();
   }
 
+  void SHEditorUI::BeginTooltip()
+  {
+    ImGui::BeginTooltip();
+  }
+
+  void SHEditorUI::EndTooltip()
+  {
+      ImGui::EndTooltip();
+  }
+
   /*-----------------------------------------------------------------------------------*/
   /* ImGui Wrapper Functions - Pop Ups                                                 */
   /*-----------------------------------------------------------------------------------*/
@@ -135,24 +150,30 @@ namespace SHADE
     return ImGui::Selectable(std::format("{} {}", icon, label).data());
   }
 
-  bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
+  bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
   {
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     return ImGui::Checkbox("#", &value);
   }
-  bool SHEditorUI::InputInt(const std::string& label, int& value)
+  bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
   {
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     return ImGui::InputInt("#", &value,
                            1, 10,
                            ImGuiInputTextFlags_EnterReturnsTrue);
   }
-  bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
+  bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
   {
     int signedVal = static_cast<int>(value);
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     const bool CHANGED = InputInt("#", signedVal);
     if (CHANGED)
@@ -162,35 +183,43 @@ namespace SHADE
     }
     return CHANGED;
   }
-  bool SHEditorUI::InputFloat(const std::string& label, float& value)
+  bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
   {
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     return ImGui::InputFloat("#", &value,
                              0.1f, 1.0f, "%.3f", 
                              ImGuiInputTextFlags_EnterReturnsTrue);
   }
-  bool SHEditorUI::InputDouble(const std::string& label, double& value)
+  bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
   {
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     return ImGui::InputDouble("#", &value,
                               0.1, 1.0, "%.3f", 
                               ImGuiInputTextFlags_EnterReturnsTrue);
   }
-  bool SHEditorUI::InputAngle(const std::string& label, double& value)
+  bool SHEditorUI::InputAngle(const std::string& label, double& value, bool* isHovered)
   {
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     return ImGui::InputDouble("#", &value,
                               1.0, 45.0, "%.3f", 
                               ImGuiInputTextFlags_EnterReturnsTrue);
   }
 
-  bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value)
+  bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered)
   {
     float val = static_cast<float>(value);
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     const bool CHANGED = ImGui::SliderFloat("#", &val,
                                             static_cast<float>(min), static_cast<float>(max), "%.3f", 
@@ -204,22 +233,24 @@ namespace SHADE
     return CHANGED;
   }
 
-  bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
+  bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered)
   {
     static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
-    return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y });
+    return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
   }
-  bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed)
+  bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered, float speed)
   {
     static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
-    return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f");
+    return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f", float{}, float{}, 0, isHovered);
   }
 
-  bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
+  bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered)
   {
     std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
     strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
     if (CHANGED)
@@ -229,13 +260,15 @@ namespace SHADE
     return CHANGED;
   }
 
-  bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
+  bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered)
   {
     // Clamp input value
     const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
     bool b = false;
 
     ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
     ImGui::SameLine();
     if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
     {
diff --git a/SHADE_Engine/src/Editor/SHEditorUI.h b/SHADE_Engine/src/Editor/SHEditorUI.h
index 13468215..b8451765 100644
--- a/SHADE_Engine/src/Editor/SHEditorUI.h
+++ b/SHADE_Engine/src/Editor/SHEditorUI.h
@@ -90,12 +90,19 @@ namespace SHADE
     static void SameLine();
 	static void Separator();
 
-	/*-----------------------------------------------------------------------------*/
+    /*-----------------------------------------------------------------------------*/
+    /* ImGui Wrapper Functions - Queries                                           */
+    /*-----------------------------------------------------------------------------*/
+    static bool IsItemHovered();
+
+    /*-----------------------------------------------------------------------------*/
 	/* ImGui Wrapper Functions - Menu                                              */
 	/*-----------------------------------------------------------------------------*/
 	static bool BeginMenu(const std::string& label);
     static bool BeginMenu(const std::string& label, const char* icon);
     static void EndMenu();
+    static void BeginTooltip();
+    static void EndTooltip();
 
     /*-----------------------------------------------------------------------------*/
     /* ImGui Wrapper Functions - Pop Ups                                           */
@@ -165,8 +172,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputCheckbox(const std::string& label, bool& value);
+    static bool InputCheckbox(const std::string& label, bool& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a integer field widget for integer input.
     /// <br/>
@@ -174,8 +182,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputInt(const std::string& label, int& value);
+    static bool InputInt(const std::string& label, int& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a integer field widget for unsigned integer input.
     /// <br/>
@@ -186,8 +195,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputUnsignedInt(const std::string& label, unsigned int& value);
+    static bool InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a decimal field widget for single precision float input.
     /// <br/>
@@ -195,8 +205,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputFloat(const std::string& label, float& value);
+    static bool InputFloat(const std::string& label, float& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a decimal field widget for double precision float input.
     /// <br/>
@@ -204,8 +215,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputDouble(const std::string& label, double& value);
+    static bool InputDouble(const std::string& label, double& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a decimal field widget for double input with increments of higher
     /// steps meant for angle variables.
@@ -214,8 +226,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputAngle(const std::string& label, double& value);
+    static bool InputAngle(const std::string& label, double& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a double slider field widget for double input.
     /// <br/>
@@ -225,8 +238,9 @@ namespace SHADE
     /// <param name="min">Minimum value of the slider.</param>
     /// <param name="max">Maximum value of the slider.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputSlider(const std::string& label, double min, double max, double& value);
+    static bool InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a 2x double field widget for Vector2 input.
     /// <br/>
@@ -234,8 +248,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputVec2(const std::string& label, SHVec2& value);
+    static bool InputVec2(const std::string& label, SHVec2& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a 3x double field widget for Vector3 input.
     /// <br/>
@@ -243,8 +258,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
+    static bool InputVec3(const std::string& label, SHVec3& value, bool* isHovered = nullptr, float speed = 0.1f);
     /// <summary>
     /// Creates a text field widget for string input.
     /// <br/>
@@ -252,8 +268,9 @@ namespace SHADE
     /// </summary>
     /// <param name="label">Label used to identify this widget.</param>
     /// <param name="value">Reference to the variable to store the result.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>True if the value was changed.</returns>
-    static bool InputTextField(const std::string& label, std::string& value);
+    static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a combo box for enumeration input.
     /// </summary>
@@ -264,17 +281,19 @@ namespace SHADE
     /// <param name="toStrFn">
     /// Conversion function from the type of enum to C-style string.
     /// </param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>Whether the value was modified.</returns>        
     template<typename Enum>
-    static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn);
+    static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn, bool* isHovered = nullptr);
     /// <summary>
     /// Creates a combo box for enumeration input using a specified list of names.
     /// </summary>
     /// <param name="label">The name of the input.</param>
     /// <param name="v">The reference to the value to modify.</param>
     /// <param name="enumNames">Vector of names for each enumeration value.</param>
+    /// <param name="isHovered>If set, stores the hover state of this widget.</param>
     /// <returns>Whether the value was modified.</returns>     
-    static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
+    static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered = nullptr);
 
 
     private:
diff --git a/SHADE_Engine/src/Editor/SHEditorUI.hpp b/SHADE_Engine/src/Editor/SHEditorUI.hpp
index f3af0412..797720e0 100644
--- a/SHADE_Engine/src/Editor/SHEditorUI.hpp
+++ b/SHADE_Engine/src/Editor/SHEditorUI.hpp
@@ -20,7 +20,7 @@ namespace SHADE
   /* ImGui Wrapper Functions - Widgets                                               */
   /*---------------------------------------------------------------------------------*/
   template<typename Enum>
-  inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn)
+  inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn, bool* isHovered)
   {
     std::vector<Enum> values;
     for (int i = 0; i <= maxVal; ++i)
@@ -28,6 +28,11 @@ namespace SHADE
       values.emplace_back(static_cast<Enum>(i));
     }
     bool b = false;
+
+    ImGui::Text(label.c_str());
+    if (isHovered)
+        *isHovered = ImGui::IsItemHovered();
+    ImGui::SameLine();
     if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
     {
       for (int i = 0; i <= maxVal; ++i)
diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp
index 3fa1789e..5788dc15 100644
--- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp
+++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp
@@ -160,7 +160,7 @@ namespace SHADE
     template <typename T, std::size_t N>
     static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
       std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
-      ImGuiSliderFlags flags = 0)
+      ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
     {
       const ImGuiWindow* const window = ImGui::GetCurrentWindow();
       if (window->SkipItems)
@@ -174,6 +174,8 @@ namespace SHADE
       ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
       ImGui::SetColumnWidth(-1, 80.0f);
       ImGui::Text(fieldLabel.c_str());
+      if (isHovered)
+          *isHovered = ImGui::IsItemHovered();
       ImGui::NextColumn();
       for (std::size_t i = 0; i < N; ++i)
       {
diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp
index c8a1fe1a..fd39da24 100644
--- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp
+++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp
@@ -99,7 +99,7 @@ namespace SHADE
 
   void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message) noexcept
   {
-    SHLOGV_INFO(message);
+    //SHLOGV_INFO(message);
   }
 
   /***************************************************************************/
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
index e842df47..ea859718 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
@@ -172,7 +172,7 @@ namespace SHADE
       // write sampler and image view
       auto& [view, sampler, layout] = imageViewsAndSamplers[i];
       writeInfo.descImageInfos[i].imageView = view->GetImageView();
-      writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
+      writeInfo.descImageInfos[i].sampler = sampler ? sampler->GetVkSampler() : nullptr;
       writeInfo.descImageInfos[i].imageLayout = layout;
     }
   }
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp
index 002aa29d..0943c489 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp
@@ -1,16 +1,18 @@
 #include "SHPch.h"
 #include "SHVkDescriptorSetLayout.h"
 #include "Graphics/Devices/SHVkLogicalDevice.h"
+#include "Graphics/Images/SHVkSampler.h"
 
 namespace SHADE
 {
     /*---------------------------------------------------------------------------------*/
     /* Constructor/Destructor                                                          */
     /*---------------------------------------------------------------------------------*/
-    SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex set, const std::vector<Binding>& bindings)
+    SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex set, const std::vector<Binding>& bindings, bool genImmutableSamplers/* = false*/)
     : device     { device }
     , layoutDesc { bindings }
     , setIndex {set}
+    , immutableSampler{}
     {
         // Check if auto-binding point calculation configuration is valid
         bool autoCalc = false;
@@ -26,6 +28,25 @@ namespace SHADE
             }
         }
 
+        vk::Sampler tempVkSampler = nullptr;
+        if (genImmutableSamplers)
+        {
+          // Create sampler
+          immutableSampler = device->CreateSampler(
+            {
+              .minFilter = vk::Filter::eLinear,
+              .magFilter = vk::Filter::eLinear,
+              .addressMode = vk::SamplerAddressMode::eRepeat,
+              .mipmapMode = vk::SamplerMipmapMode::eLinear,
+              .minLod = -1000,
+              .maxLod = 1000
+            }
+          );
+
+          tempVkSampler = immutableSampler->GetVkSampler();
+        }
+
+
         // Fill up VK bindings with auto calculated bind points if needed
         std::vector<vk::DescriptorSetLayoutBinding> layoutBindings;
         layoutBindings.reserve(bindings.size());
@@ -39,7 +60,7 @@ namespace SHADE
                 .descriptorType     = binding.Type,
                 .descriptorCount    = binding.DescriptorCount,
                 .stageFlags         = binding.Stage,
-                .pImmutableSamplers = nullptr // We will create our own samplers
+                .pImmutableSamplers = genImmutableSamplers ? &tempVkSampler : nullptr,
             };
             layoutBindings.emplace_back(VK_BINDING);
 
@@ -75,7 +96,8 @@ namespace SHADE
       : device {rhs.device}
       , setLayout {rhs.setLayout}
       , layoutDesc{std::move (rhs.layoutDesc)}
-      , setIndex {rhs.setIndex}
+      , setIndex{ rhs.setIndex }
+      , immutableSampler{ rhs.immutableSampler }
     {
       rhs.setLayout = VK_NULL_HANDLE;
     }
@@ -106,6 +128,7 @@ namespace SHADE
       setLayout = rhs.setLayout;
       layoutDesc = std::move(rhs.layoutDesc);
       setIndex = rhs.setIndex;
+      immutableSampler = rhs.immutableSampler;
 
       rhs.setLayout = VK_NULL_HANDLE;
 
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h
index 9b436026..4fffbc96 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h
@@ -10,6 +10,7 @@ namespace SHADE
     /* Forward Declarations                                                            */
     /*---------------------------------------------------------------------------------*/
     class SHVkLogicalDevice;
+    class SHVkSampler;
 
     /*---------------------------------------------------------------------------------*/
     /* Type Definitions                                                                */
@@ -74,7 +75,7 @@ namespace SHADE
         /// </summary>
         /// <param name="device"></param>
         /// <param name="bindings"></param>
-        SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex setIndex, const std::vector<Binding>& bindings);
+        SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex setIndex, const std::vector<Binding>& bindings, bool genImmutableSamplers = false);
         SHVkDescriptorSetLayout(const SHVkDescriptorSetLayout&) = delete;
         SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept;
         /// <summary>
@@ -107,5 +108,6 @@ namespace SHADE
         vk::DescriptorSetLayout   setLayout;
         std::vector<Binding>      layoutDesc; // Stores description of the layout
         SetIndex                  setIndex;   // Index of the set
+        Handle<SHVkSampler>       immutableSampler;
     };
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
index 4f4f94a4..7c7acfc5 100644
--- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
+++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
@@ -550,10 +550,9 @@ namespace SHADE
 
   }
 
-  Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept
+  Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers/* = false*/) noexcept
   {
-    return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex,  bindings);
-
+    return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex,  bindings, genImmutableSamplers);
   }
 
   Handle<SHVkDescriptorPool> SHVkLogicalDevice::CreateDescriptorPools(const SHVkDescriptorPool::Config& config /*= {}*/) noexcept
diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
index 5c400e02..6f7048b8 100644
--- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
+++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
@@ -186,7 +186,7 @@ namespace SHADE
     Handle<SHVkRenderpass>          CreateRenderpass          (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
     Handle<SHVkRenderpass>          CreateRenderpass          (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
     Handle<SHVkFramebuffer>         CreateFramebuffer         (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
-    Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept;
+    Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers = false) noexcept;
     Handle<SHVkDescriptorPool>      CreateDescriptorPools     (const SHVkDescriptorPool::Config& config = {}) noexcept;
     Handle<SHVkDescriptorSetGroup>  CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
       std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,
diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp
index f12b834d..4300f2bd 100644
--- a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp
+++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp
@@ -24,14 +24,15 @@ namespace SHADE
   {
     const vk::SamplerCreateInfo SAMPLER_CREATE_INFO
     {
-      .magFilter    = params.magFilter,
-      .minFilter    = params.minFilter,
-      .mipmapMode   = params.mipmapMode,
-      .addressModeU = params.addressMode,
-      .addressModeV = params.addressMode,
-      .addressModeW = params.addressMode,
-      .minLod       = params.minLod,
-      .maxLod       = params.maxLod
+      .magFilter     = params.magFilter,
+      .minFilter     = params.minFilter,
+      .mipmapMode    = params.mipmapMode,
+      .addressModeU  = params.addressMode,
+      .addressModeV  = params.addressMode,
+      .addressModeW  = params.addressMode,
+      .maxAnisotropy = 1.0f,
+      .minLod        = params.minLod,
+      .maxLod        = params.maxLod,
     };
 
     // Create the sampler
@@ -39,7 +40,8 @@ namespace SHADE
   }
 
   SHVkSampler::SHVkSampler(SHVkSampler&& rhs) noexcept
-  : vkSampler { rhs.vkSampler }
+    : vkSampler{ rhs.vkSampler }
+    , device{ rhs.device }
   {
     rhs.vkSampler = nullptr;    
   }
@@ -56,6 +58,7 @@ namespace SHADE
   SHADE::SHVkSampler& SHVkSampler::operator=(SHVkSampler&& rhs) noexcept
   {
     vkSampler = rhs.vkSampler;
+    device = rhs.device;
     rhs.vkSampler = nullptr;
     return *this;
   }
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
index ac2f1f8c..67cbc001 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
@@ -25,6 +25,12 @@ namespace SHADE
   struct SHGraphicsConstants
   {
   public:
+    struct RenderGraphIndices
+    {
+      static constexpr uint32_t WORLD  = 0;
+      static constexpr uint32_t EDITOR = 0;
+    };
+
     struct DescriptorSetIndex
     {
       /***************************************************************************/
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
index c31b8c4d..143f3bf5 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
@@ -36,11 +36,9 @@ of DigiPen Institute of Technology is prohibited.
 
 namespace SHADE
 {
+#pragma region INIT_EXIT
 
-  /*---------------------------------------------------------------------------------*/
-  /* Constructor/Destructors                                                         */
-  /*---------------------------------------------------------------------------------*/
-  void SHGraphicsSystem::Init(void)
+  void SHGraphicsSystem::InitBoilerplate(void) noexcept
   {
     /*-----------------------------------------------------------------------*/
     /* BACKEND BOILERPLATE                                                   */
@@ -51,7 +49,7 @@ namespace SHADE
     // Get Physical Device and Construct Logical Device
     physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
     device = SHVkInstance::CreateLogicalDevice({ SHQueueParams(SH_Q_FAM::GRAPHICS, SH_QUEUE_SELECT::DEDICATED), SHQueueParams(SH_Q_FAM::TRANSFER, SH_QUEUE_SELECT::DEDICATED) }, physicalDevice);
-      
+
     // Construct surface
     surface = device->CreateSurface(window->GetHWND());
 
@@ -71,7 +69,15 @@ namespace SHADE
         if (width == 0 || height == 0)
           return;
 
-        renderContext.SetIsResized(true);
+#ifdef SHEDITOR
+
+        //PrepareResize(1, 1, SHVec2(0, 0));
+
+#else
+
+        PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0));
+
+#endif
       });
 
     window->RegisterWindowCloseCallback([&](void)
@@ -106,11 +112,12 @@ namespace SHADE
     graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
     transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
     graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
+  }
 
-
-
+  void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
+  {
     /*-----------------------------------------------------------------------*/
-    /* MIDDLE END SETUP                                                      
+    /* MIDDLE END SETUP
        - Viewports
        - Renderer
        - Render graph in renderers
@@ -118,8 +125,8 @@ namespace SHADE
        - Default vertex input state
        - Global data
     /*-----------------------------------------------------------------------*/
+    auto windowDims = window->GetWindowSize();
 
-    SHGraphicsGlobalData::Init(device);
 
     // Set Up Cameras
     screenCamera = resourceManager.Create<SHCamera>();
@@ -131,12 +138,12 @@ namespace SHADE
     worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
 
     // Create Default Viewport
-    defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
-    
+    worldViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
+
     // Get render graph from default viewport world renderer
     worldRenderGraph = resourceManager.Create<SHRenderGraph>();
-    
-    std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
+
+    std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
     for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
     {
       renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
@@ -144,44 +151,27 @@ namespace SHADE
 
     // Initialize world render graph
     worldRenderGraph->Init(device, swapchain);
-    worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
-    worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
-    worldRenderGraph->AddResource("Entity ID", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
+    worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
+    worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
+    worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
 
-    //worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
-    //worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
-    //worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
-    //worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
-    auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Present"}, {}); // no predecessors
+    auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
 
      //First subpass to write to G-Buffer
     auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
-    gBufferWriteSubpass->AddColorOutput("Present");
+    gBufferWriteSubpass->AddColorOutput("Scene");
     gBufferWriteSubpass->AddColorOutput("Entity ID");
-    gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL);
+    gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
 
+    // We do this to just transition our scene layout to shader read
+    auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
+    sceneLayoutTransitionSubpass->AddInput("Scene");
 
-    // TODO: Use macro to add this node when SH_EDITOR is enabled
-    auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
-    auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
-    imguiSubpass->AddColorOutput("Present");
-
+    // Generate world render graph
     worldRenderGraph->Generate();
 
-    // Create Semaphore
-    for (auto& semaHandle : graphSemaphores)
-    {
-      semaHandle = device->CreateSemaphore();
-    }
-
-    // Create Debug Renderers
-    /*debugScreenRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
-    debugScreenRenderer->SetCamera(screenCamera);
-    debugWorldRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
-    debugWorldRenderer->SetCamera(worldCamera);*/
-
     // Add world renderer to default viewport
-    worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
+    worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
     worldRenderer->SetCamera(worldCamera);
 
 
@@ -198,17 +188,97 @@ namespace SHADE
     cubeFS->Reflect();
 
     defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
+  }
+
+  void SHGraphicsSystem::InitMiddleEnd(void) noexcept
+  {
+    SHGraphicsGlobalData::Init(device);
+
+    InitSceneRenderGraph();
+
+#ifdef SHEDITOR
+    InitEditorRenderGraph();
+#endif
+
+    // Create Semaphore
+    for (auto& semaHandle : graphSemaphores)
+    {
+      semaHandle = device->CreateSemaphore();
+    }
+  }
+
+  void SHGraphicsSystem::InitSubsystems(void) noexcept
+  {
 
     mousePickSystem = resourceManager.Create<SHMousePickSystem>();
 
     std::vector<Handle<SHVkCommandPool>> cmdPools;
     cmdPools.reserve(swapchain->GetNumImages());
     for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
-    	cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
+      cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
 
     mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
+
+    // Register the post offscreen render to the system
+    postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
+    postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
   }
 
+#ifdef SHEDITOR
+  void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept
+  {
+    auto windowDims = window->GetWindowSize();
+
+    // Create Default Viewport
+    editorViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 1.0f));
+
+    // Get render graph from viewport editor renderer
+    editorRenderGraph = resourceManager.Create<SHRenderGraph>();
+
+    std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
+    for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
+      renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
+
+    editorRenderGraph->Init(device, swapchain);
+    editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
+
+
+    auto imguiNode = editorRenderGraph->AddNode("ImGui Node", { "Present"}, {});
+    auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
+    imguiSubpass->AddColorOutput("Present");
+
+    // Generate world render graph
+    editorRenderGraph->Generate();
+
+    // Add world renderer to default viewport
+    editorRenderer = editorViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], editorRenderGraph);
+    editorRenderer->SetCamera(worldCamera);
+  }
+#endif
+
+  /*---------------------------------------------------------------------------------*/
+  /* Constructor/Destructors                                                         */
+  /*---------------------------------------------------------------------------------*/
+  void SHGraphicsSystem::Init(void)
+  {
+    InitBoilerplate();
+    InitMiddleEnd();
+    InitSubsystems();
+
+
+  }
+
+  void SHGraphicsSystem::Exit(void)
+  {
+  }
+
+#pragma endregion INIT_EXIT
+
+#pragma region LIFECYCLE
+
+  /*---------------------------------------------------------------------------------*/
+  /* Lifecycle Functions                                                             */
+  /*---------------------------------------------------------------------------------*/
   /***************************************************************************/
   /*!
   
@@ -227,12 +297,6 @@ namespace SHADE
     if (window->IsMinimized() || renderContext.GetWindowIsDead())
       return;
 
-    if (renderContext.GetResized())
-    {
-      return;
-    }
-
-
     // Frame data for the current frame
     auto const& frameData = renderContext.GetCurrentFrameData();
     uint32_t frameIndex = renderContext.GetCurrentFrame();
@@ -328,14 +392,7 @@ namespace SHADE
       }
     }
   }
-
-  void SHGraphicsSystem::Exit(void)
-  {
-  }
-
-  /*---------------------------------------------------------------------------------*/
-  /* Lifecycle Functions                                                             */
-  /*---------------------------------------------------------------------------------*/
+  
   /***************************************************************************/
   /*!
 
@@ -400,12 +457,6 @@ namespace SHADE
     if (window->IsMinimized() || renderContext.GetWindowIsDead())
       return;
 
-    if (renderContext.GetResized())
-    {
-      return;
-    }
-
-
     const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
     auto& currFrameData = renderContext.GetCurrentFrameData();
 
@@ -417,9 +468,7 @@ namespace SHADE
       // If swapchain is incompatible/outdated
       if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
       {
-
         HandleResize();
-
       }
     }
 
@@ -427,6 +476,10 @@ namespace SHADE
     renderContext.AdvanceFrame();
   }
 
+#pragma endregion LIFECYCLE
+
+#pragma region ADD_REMOVE_BUILD
+
   Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport)
   {
     // Create the viewport
@@ -537,36 +590,9 @@ namespace SHADE
       );
   }
 
-  void SHGraphicsSystem::HandleResize(void) noexcept
-  {
-    if (window->IsMinimized() || renderContext.GetWindowIsDead())
-      return;
-
-    auto windowDims = window->GetWindowSize();
-
-    // Resize the swapchain
-    swapchain->Resize(surface, windowDims.first, windowDims.second);
-
-    renderContext.HandleResize();
-
-    worldRenderGraph->HandleResize(windowDims.first, windowDims.second);
-
-    defaultViewport->SetWidth(static_cast<float>(windowDims.first));
-    defaultViewport->SetHeight(static_cast<float>(windowDims.second));
-
-    worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
-  }
-  
-  void SHGraphicsSystem::AwaitGraphicsExecution()
-  {
-    device->WaitIdle();
-  }
-
-  void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
-  {
-    window = wind;
-  }
+#pragma endregion ADD_REMOVE
 
+#pragma region ROUTINES
   /*-----------------------------------------------------------------------------------*/
   /* System Routine Functions - BeginRoutine                                           */
   /*-----------------------------------------------------------------------------------*/
@@ -638,5 +664,62 @@ namespace SHADE
       renderable.ResetChangedFlag();
     }
   }
+#pragma endregion ROUTINES
 
+#pragma region MISC
+
+  void SHGraphicsSystem::PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept
+  {
+    resizeWidth = newWidth;
+    resizeHeight = newHeight;
+
+    renderContext.SetIsResized(true);
+  }
+
+  void SHGraphicsSystem::HandleResize(void) noexcept
+  {
+    device->WaitIdle();
+
+    if (window->IsMinimized() || renderContext.GetWindowIsDead())
+      return;
+
+    graphSemaphores[0].Free();
+    graphSemaphores[1].Free();
+
+    auto windowDims = window->GetWindowSize();
+
+    // Resize the swapchain
+    swapchain->Resize(surface, windowDims.first, windowDims.second);
+
+    renderContext.HandleResize();
+
+    worldRenderGraph->HandleResize(resizeWidth, resizeHeight);
+    editorRenderGraph->HandleResize(windowDims.first, windowDims.second);
+
+    mousePickSystem->HandleResize();
+    postOffscreenRender->HandleResize();
+
+    worldViewport->SetWidth(static_cast<float>(resizeWidth));
+    worldViewport->SetHeight(static_cast<float>(resizeHeight));
+
+    worldCamera->SetPerspective(90.0f, static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.0f, 100.0f);
+
+    for (auto& semaHandle : graphSemaphores)
+      semaHandle = device->CreateSemaphore();
+
+
+  }
+  
+  void SHGraphicsSystem::AwaitGraphicsExecution()
+  {
+    device->WaitIdle();
+  }
+
+  void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
+  {
+    window = wind;
+  }
+
+
+#pragma endregion MISC
 }
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
index 3160cd57..7d0fa3ab 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
@@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
 #include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
 #include "../Textures/SHTextureLibrary.h"
 #include "../Textures/SHVkSamplerCache.h"
+#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
 
 namespace SHADE
 {
@@ -66,6 +67,16 @@ namespace SHADE
   /***********************************************************************************/
   class SH_API SHGraphicsSystem : public SHSystem
   {
+  private:
+    void InitBoilerplate       (void) noexcept;
+    void InitSceneRenderGraph  (void) noexcept;
+    void InitMiddleEnd         (void) noexcept;
+    void InitSubsystems        (void) noexcept;
+
+#ifdef SHEDITOR
+    void InitEditorRenderGraph (void) noexcept;
+#endif
+
   public:
     class SH_API BeginRoutine final : public SHSystemRoutine
     {
@@ -251,6 +262,7 @@ namespace SHADE
     /***************************************************************************/
     void BuildTextures();
 
+    void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
     void HandleResize(void) noexcept;
     void AwaitGraphicsExecution();
 
@@ -262,20 +274,25 @@ namespace SHADE
     /*-----------------------------------------------------------------------------*/
     /* Getters (Temporary)                                                         */
     /*-----------------------------------------------------------------------------*/
-    Handle<SHVkLogicalDevice> GetDevice() const { return device; }
-    Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
-    Handle<SHVkSurface> GetSurface() const { return surface; }
-    Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
-    Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
-    Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
-    Handle<SHViewport> GetDefaultViewport() const {return defaultViewport;}
-    Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
+    Handle<SHVkLogicalDevice>           GetDevice() const { return device; }
+    Handle<SHVkSwapchain>               GetSwapchain() const { return swapchain; }
+    Handle<SHVkSurface>                 GetSurface() const { return surface; }
+    Handle<SHVkPhysicalDevice>          GetPhysicalDevice() const { return physicalDevice; }
+    Handle<SHVkQueue>                   GetQueue() const { return graphicsQueue; }
+    Handle<SHVkDescriptorPool>          GetDescriptorPool() const { return descPool; }
+    Handle<SHViewport>                  GetDefaultViewport() const {return worldViewport;}
+#ifdef SHEDITOR
+    Handle<SHViewport>                  GetEditorViewport () const {return editorViewport;};
+#endif
+    Handle<SHMousePickSystem>           GetMousePickSystem(void) const noexcept {return mousePickSystem;};
+    Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
     //SHRenderGraph const& GetRenderGraph(void) const noexcept;
 
     //Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
 
 
   private:
+
     /*-----------------------------------------------------------------------------*/
     /* Data Members                                                                */
     /*-----------------------------------------------------------------------------*/
@@ -296,13 +313,19 @@ namespace SHADE
     SHWindow*                                                 window = nullptr;
 
     // Middle End Resources
-	  ResourceManager                                           resourceManager;
+    ResourceManager                                           resourceManager;
     SHMeshLibrary                                             meshLibrary;
     SHTextureLibrary                                          texLibrary;
     SHSamplerCache                                            samplerCache;
     SHMaterialInstanceCache                                   materialInstanceCache;
     // Viewports 
-    Handle<SHViewport>                                        defaultViewport;    // Whole screen
+#ifdef SHEDITOR
+    Handle<SHViewport>                                        editorViewport;
+    Handle<SHRenderer>                                        editorRenderer;
+    Handle<SHRenderGraph>                                     editorRenderGraph;
+#endif
+
+    Handle<SHViewport>                                        worldViewport;    // Whole screen
     std::vector<Handle<SHViewport>>                           viewports;          // Additional viewports
 
     // Debug Renderers
@@ -327,5 +350,9 @@ namespace SHADE
 
     // Sub systems
     Handle<SHMousePickSystem>                                 mousePickSystem;
+    Handle<SHPostOffscreenRenderSystem>                       postOffscreenRender;
+
+    uint32_t                                                  resizeWidth;
+    uint32_t                                                  resizeHeight;
   };
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp
index 8522a8d5..57a08d47 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp
@@ -6,11 +6,16 @@
 #include "Graphics/Synchronization/SHVkFence.h"
 #include "Graphics/Buffers/SHVkBuffer.h"
 #include "Graphics/SHVkUtil.h"
+#include "Graphics/MiddleEnd/Interface/SHViewport.h"
 
 namespace SHADE
 {
-  void SHMousePickSystem::Init(Handle<SHVkLogicalDevice> logicalDevice, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept
+  void SHMousePickSystem::Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept
   {
+    logicalDevice = device;
+
+    pickedEID = MAX_EID;
+
     // Create command buffers
     for (auto& pool : cmdPools)
     {
@@ -20,13 +25,7 @@ namespace SHADE
     // assign the attachment
     entityIDAttachment = eidAttachment;
     
-    // Create the fence
-    afterCopyFence = logicalDevice->CreateFence();
-
-    uint32_t bufferSize = entityIDAttachment->GetWidth() * eidAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
-
-    // Create the buffer
-    imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT |  VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
+    HandleResize();
   }
 
   void SHMousePickSystem::Run(Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept
@@ -54,13 +53,36 @@ namespace SHADE
       // wait for the copy to be done
       afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
 
-      int mouseX = 0, mouseY = 0;
-      SHInputManager::GetMouseWindowPosition(&mouseX, &mouseY);
+      pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
 
-      pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(mouseY * entityIDAttachment->GetWidth() + mouseX);
     }
   }
 
+  void SHMousePickSystem::HandleResize(void) noexcept
+  {
+    if (afterCopyFence)
+    {
+      afterCopyFence->Reset();
+      afterCopyFence.Free();
+    }
+
+    if (imageDataDstBuffer)
+      imageDataDstBuffer.Free();
+
+    // Create the fence
+    afterCopyFence = logicalDevice->CreateFence();
+
+    uint32_t bufferSize = entityIDAttachment->GetWidth() * entityIDAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
+
+    // Create the buffer
+    imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
+  }
+
+  void SHMousePickSystem::SetViewportMousePos(SHVec2 vpMousePos) noexcept
+  {
+    viewportMousePos = vpMousePos;
+  }
+
   EntityID SHMousePickSystem::GetPickedEntity(void) const noexcept
   {
     return pickedEID;
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h
index 7ec193b4..85e86969 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h
@@ -13,10 +13,13 @@ namespace SHADE
   class SHVkFence;
   class SHVkQueue;
   class SHVkBuffer;
+  class SHViewport;
 
   class SHMousePickSystem
   {
   private:
+    Handle<SHVkLogicalDevice>     logicalDevice;
+
     //! Handle to the render graph resource that will contain the entity IDs
     Handle<SHRenderGraphResource> entityIDAttachment; 
 
@@ -30,17 +33,24 @@ namespace SHADE
     Handle<SHVkBuffer> imageDataDstBuffer;
 
     //! eid picked from screen
-    EntityID pickedEID = MAX_EID;
+    EntityID pickedEID;
+
+    //! mouse position relative to the viewport window displaying the world
+    SHVec2 viewportMousePos;
+
   public:
     /*-----------------------------------------------------------------------*/
     /* PUBLIC MEMBER FUNCTIONS                                              */
     /*-----------------------------------------------------------------------*/
-    void Init(Handle<SHVkLogicalDevice> logicalDevice, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept;
+    void Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept;
     void Run (Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept; 
+    void HandleResize (void) noexcept;
 
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
     /*-----------------------------------------------------------------------*/
+    void SetViewportMousePos (SHVec2 vpMousePos) noexcept;
+
     EntityID GetPickedEntity (void) const noexcept;
 
   };
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp
new file mode 100644
index 00000000..8b41a979
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp
@@ -0,0 +1,84 @@
+#include "SHpch.h"
+#include "SHPostOffscreenRenderSystem.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
+#include "Graphics/Descriptors/SHVkDescriptorPool.h"
+#include "Graphics/Devices/SHVkLogicalDevice.h"
+#include "Graphics/Images/SHVkSampler.h"
+#include "Graphics/RenderGraph/SHRenderGraphResource.h"
+
+namespace SHADE
+{
+  /***************************************************************************/
+  /*!
+  
+    \brief
+      This function basically creates the entities required for offscreen
+      rendering. It takes in a render graph resource. Side note: it creates
+      a descriptor set layout that is similar to the one created in imgui. This
+      is so that the descriptor set passed to imGui won't be invalid.
+    
+    \param logicalDevice
+      For vulkan object creation
+
+    \param renderGraphResource
+      The resource in which has been 
+
+    \param descriptorPool
+   
+    \return 
+  
+  */
+  /***************************************************************************/
+  void SHPostOffscreenRenderSystem::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHRenderGraphResource> renderGraphResource, Handle<SHVkDescriptorPool> descriptorPool) noexcept
+  {
+    offscreenRender = renderGraphResource;
+
+    // Create sampler
+    offscreenRenderSampler = logicalDevice->CreateSampler(
+      {
+        .minFilter = vk::Filter::eLinear,
+        .magFilter = vk::Filter::eLinear,
+        .addressMode = vk::SamplerAddressMode::eRepeat,
+        .mipmapMode = vk::SamplerMipmapMode::eLinear,
+        .minLod = -1000,
+        .maxLod = 1000
+      }
+    );
+
+    // Create descriptor set layout binding
+    SHVkDescriptorSetLayout::Binding imageBinding
+    {
+      .Type = vk::DescriptorType::eCombinedImageSampler,
+      .Stage = vk::ShaderStageFlagBits::eFragment,
+      .BindPoint = 0,
+      .DescriptorCount = 1,
+    };
+
+    // Create descriptor set layout
+    offscreenRenderDescSetLayout = logicalDevice->CreateDescriptorSetLayout(0, { imageBinding }, false);
+
+    // Create descriptor set
+    offscreenRenderDescSet = descriptorPool->Allocate({ offscreenRenderDescSetLayout }, { 1 });
+    
+    HandleResize();
+  }
+
+  void SHPostOffscreenRenderSystem::HandleResize(void) noexcept
+  {
+    std::vector combinedImageSampler
+    {
+      std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
+    };
+
+    // Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
+    offscreenRenderDescSet->ModifyWriteDescImage(0, 0, combinedImageSampler);
+    offscreenRenderDescSet->UpdateDescriptorSetImages(0, 0);
+  }
+
+  Handle<SHVkDescriptorSetGroup> SHPostOffscreenRenderSystem::GetDescriptorSetGroup(void) const noexcept
+  {
+    return offscreenRenderDescSet;
+  }
+
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h
new file mode 100644
index 00000000..d3360b87
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "Resource/Handle.h"
+
+namespace SHADE
+{
+  class SHVkLogicalDevice;
+  class SHVkDescriptorSetLayout;
+  class SHVkDescriptorSetGroup;
+  class SHVkDescriptorPool;
+  class SHVkSampler;
+  class SHRenderGraphResource;
+
+  class SHPostOffscreenRenderSystem
+  {
+  private:
+    Handle<SHRenderGraphResource>   offscreenRender;
+    
+    Handle<SHVkDescriptorSetLayout> offscreenRenderDescSetLayout;
+    Handle<SHVkDescriptorSetGroup>  offscreenRenderDescSet;
+    Handle<SHVkSampler>             offscreenRenderSampler;
+
+  public:
+    void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHRenderGraphResource> renderGraphResource, Handle<SHVkDescriptorPool> descriptorPool) noexcept;
+    //void Run ()
+
+    void HandleResize (void) noexcept;
+
+    Handle<SHVkDescriptorSetGroup> GetDescriptorSetGroup (void) const noexcept;
+  };
+}
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
index 14af56ee..425e9c81 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
@@ -75,12 +75,15 @@ namespace SHADE
 
   void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
   {
-    cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
-    cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
+    if (camera)
+    {
+      cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
+      cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
 
-      std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
+        std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
 
-    cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
+      cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
+    }
   }
 
   void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp
index dc534a49..f47920e0 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp
@@ -85,4 +85,14 @@ namespace SHADE
 
   }
 
+  void SHViewport::SetX(float x) noexcept
+  {
+		viewport.x = x;
+  }
+
+  void SHViewport::SetY(float y) noexcept
+  {
+    viewport.y = y;
+  }
+
 }
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h
index 221dbe7e..04b39f00 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h
@@ -67,6 +67,8 @@ namespace SHADE
 		/*-----------------------------------------------------------------------------*/
 		void SetWidth(float w) noexcept;
 		void SetHeight (float h) noexcept;
+		void SetX (float x) noexcept;
+		void SetY (float y) noexcept;
 
 		/*-----------------------------------------------------------------------------*/
 		/* Getters                                                                     */
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp
index 0ac7013a..8041adfd 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp
@@ -52,7 +52,6 @@ namespace SHADE
       {
         frameData[i].cmdPoolHdls.push_back(logicalDeviceHdl->CreateCommandPool(params.cmdPoolQueueFamilyType, params.cmdPoolResetMode, params.cmdBufferTransient));
       }
-
     }
 
     // Initialize all the info.
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.cpp
new file mode 100644
index 00000000..6e01269e
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.cpp
@@ -0,0 +1,7 @@
+#include "SHpch.h"
+#include "SHAttachmentDescInitParams.h"
+
+namespace SHADE
+{
+
+}
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.h b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.h
new file mode 100644
index 00000000..20e924cb
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescInitParams.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "Resource/Handle.h"
+
+namespace SHADE
+{
+  class SHRenderGraphResource;
+
+  struct SHAttachmentDescInitParams
+  {
+    Handle<SHRenderGraphResource> resourceHdl;
+    bool dontClearOnLoad{false};
+  };
+}
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
index dc21fa37..241292d4 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
@@ -3,12 +3,13 @@
 namespace SHADE
 {
   // Used for attachment description creation for renderpass node
-  enum class SH_ATT_DESC_TYPE
+  enum class SH_ATT_DESC_TYPE_FLAGS
   {
-    COLOR,
-    COLOR_PRESENT,
-    DEPTH,
-    STENCIL,
-    DEPTH_STENCIL,
+    COLOR = 0x01,
+    COLOR_PRESENT = 0x02,
+    DEPTH = 0x04,
+    STENCIL = 0x08,
+    DEPTH_STENCIL = 0x10,
+    INPUT = 0x20
   };
 }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
index 1861f6d2..98cb6709 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
@@ -8,10 +8,17 @@
 #include "Graphics/Framebuffer/SHVkFramebuffer.h"
 #include "Graphics/Buffers/SHVkBuffer.h"
 #include "Tools/SHLogger.h"
+#include "SHAttachmentDescInitParams.h"
 
 namespace SHADE
 {
-  
+
+  SHRenderGraph::ResourceInstruction::ResourceInstruction(char const* resourceName, bool dontClearOnLoad /*= false*/) noexcept
+    : resourceName{ resourceName }
+    , dontClearOnLoad{ dontClearOnLoad }
+  {
+
+  }
 
   /***************************************************************************/
   /*!
@@ -40,7 +47,7 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
+  void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
   {
     // If we set to 
     if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
@@ -50,7 +57,7 @@ namespace SHADE
       format = swapchainHdl->GetSurfaceFormatKHR().format;
     }
 
-    graphResources.try_emplace(resourceName, resourceManager.Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, type, format, w, h, levels, usageFlags, createFlags));
+    graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
   }
 
   /***************************************************************************/
@@ -82,7 +89,7 @@ namespace SHADE
       {
         for (auto& color : subpass->colorReferences)
         {
-          if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
+          if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
             resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
           else
             resourceAttLayouts[color.attachment] = color.layout;
@@ -95,11 +102,11 @@ namespace SHADE
           resourceAttLayouts[input.attachment] = input.layout;
       }
 
-      for (uint32_t i = 0; i < node->attachmentDescriptions.size(); ++i)
+      for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
       {
-        auto& att = node->attachmentDescriptions[i];
+        auto& att = node->attachmentDescriptions[j];
         att.initialLayout = vk::ImageLayout::eUndefined;
-        att.finalLayout = resourceAttLayouts[i];
+        att.finalLayout = resourceAttLayouts[j];
       }
       ++i;
     }
@@ -210,10 +217,18 @@ namespace SHADE
         for (auto& inputAtt : subpass->inputReferences)
         {
           auto resource = node->attResources[inputAtt.attachment];
-          if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
-            colorRead |= (1 << i);
-          else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL)
-            depthRead |= (1 << i);
+          if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::INPUT))
+          {
+              if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR) ||
+                  resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
+              colorRead |= (1 << i);
+            else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL))
+              depthRead |= (1 << i);
+          }
+          else
+          {
+            SHLOG_ERROR("While configuring subpass, an input reference was detected but the resource to be used is not marked as SH_ATT_DESC_TYPE_FLAGS::INPUT. ");
+          }
         }
 
         ++i;
@@ -350,10 +365,9 @@ namespace SHADE
     , swapchainHdl{ }
     , nodes{}
     , graphResources{}
-    , resourceManager{}
-
+    , resourceManager{nullptr}
   {
-
+    resourceManager = std::make_shared<ResourceManager>();
   }
 
   SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
@@ -400,7 +414,7 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  Handle<SHRenderGraphNode> SHRenderGraph::AddNode(std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept
+  SHADE::Handle<SHADE::SHRenderGraphNode> SHRenderGraph::AddNode(std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept
   {
     if (nodeIndexing.contains(nodeName))
     {
@@ -408,12 +422,19 @@ namespace SHADE
       return {};
     }
 
-    std::vector<Handle<SHRenderGraphResource>> resources;
-    for (auto const& name : resourceNames)
+    std::vector<SHAttachmentDescInitParams> descInitParams;
+    for (auto const& instruction : resourceInstruction)
     {
       // If the resource that the new node is requesting for exists, allow the graph to reference it
-      if (graphResources.contains(name))
-        resources.push_back(graphResources.at(name));
+      if (graphResources.contains(instruction.resourceName))
+      {
+        descInitParams.push_back(
+          {
+            .resourceHdl = graphResources.at(instruction.resourceName),
+            .dontClearOnLoad = false, 
+          }
+        );
+      }
       else
       {
         SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node.");
@@ -435,7 +456,7 @@ namespace SHADE
       }
     }
 
-    nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources));
+    nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(descInitParams), std::move(predecessors), &graphResources));
     nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
     return nodes.at(nodeIndexing[nodeName]);
   }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
index cfc29bc2..952c6d8f 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <map>
+#include <memory>
 
 namespace SHADE
 {
@@ -33,7 +34,17 @@ namespace SHADE
 
   class SH_API SHRenderGraph
   {
+  public:
+    struct ResourceInstruction
+    {
+      std::string resourceName;
+      bool dontClearOnLoad;
+
+      ResourceInstruction (char const* resourceName, bool dontClearOnLoad = false) noexcept;
+    };
+
   private:
+
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER FUNCTIONS                                              */
     /*-----------------------------------------------------------------------*/
@@ -60,7 +71,7 @@ namespace SHADE
     std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
 
     //! Resource library for graph handles
-    ResourceManager resourceManager;
+    std::shared_ptr<ResourceManager> resourceManager;
 
   public:
     /*-----------------------------------------------------------------------*/
@@ -74,13 +85,14 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PUBLIC MEMBER FUNCTIONS                                               */
     /*-----------------------------------------------------------------------*/
-    void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
-    void                      AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
-    Handle<SHRenderGraphNode> AddNode      (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
+    void                      Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
+    void                      AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
+    Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
+    
     void                      Generate     (void) noexcept;
-    void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
-    void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
-    void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
+    void                      Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
+    void                      FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
+    void                      HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
 
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
index ea09dd47..ec184386 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
@@ -42,7 +42,7 @@ namespace SHADE
 
       for (uint32_t j = 0; j < attResources.size(); ++j)
       {
-        uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
+        uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
         imageViews[j] = attResources[j]->imageViews[imageViewIndex];
 
         // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@@ -69,7 +69,7 @@ namespace SHADE
 
       for (uint32_t j = 0; j < attResources.size(); ++j)
       {
-        uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
+        uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
         imageViews[j] = attResources[j]->imageViews[imageViewIndex];
 
         // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@@ -104,14 +104,14 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
+  SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<ResourceManager> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
     : logicalDeviceHdl{ logicalDevice }
     , renderpass{}
     , framebuffers{}
     , prereqNodes{ std::move(predecessors) }
     , attachmentDescriptions{}
     , resourceAttachmentMapping{}
-    , attResources{ std::move(attRes) }
+    , attResources{ }
     , subpasses{}
     , executed{ false }
     , configured{ false }
@@ -121,6 +121,12 @@ namespace SHADE
     // pipeline library initialization
     pipelineLibrary.Init(logicalDeviceHdl);
 
+    // Store all the handles to resources
+    attResources.reserve (attDescInitParams.size());
+    for (auto& param : attDescInitParams)
+      attResources.push_back(param.resourceHdl);
+
+    // We have as many descriptions as we have resources
     attachmentDescriptions.resize(attResources.size());
 
     bool containsSwapchainImage = false;
@@ -140,7 +146,7 @@ namespace SHADE
 
       newDesc.format = attResources[i]->resourceFormat;
 
-      if (attResources[i]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
+      if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
         containsSwapchainImage = true;
 
       resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
@@ -156,7 +162,7 @@ namespace SHADE
   }
 
   SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
-    : resourceManager{ rhs.resourceManager }
+    : resourceManager{ std::move (rhs.resourceManager) }
     , logicalDeviceHdl{ rhs.logicalDeviceHdl }
     , renderpass{ rhs.renderpass }
     , framebuffers{ std::move(rhs.framebuffers) }
@@ -171,6 +177,8 @@ namespace SHADE
     , ptrToResources{ rhs.ptrToResources }
     , pipelineLibrary{ std::move(rhs.pipelineLibrary) }
     , batcher{ std::move(rhs.batcher) }
+    , spDescs{ std::move(rhs.spDescs) }
+    , spDeps{ std::move(rhs.spDeps) }
 
   {
     rhs.renderpass = {};
@@ -181,7 +189,7 @@ namespace SHADE
     if (&rhs == this)
       return *this;
 
-    resourceManager = rhs.resourceManager;
+    resourceManager = std::move(rhs.resourceManager);
     logicalDeviceHdl = rhs.logicalDeviceHdl;
     renderpass = rhs.renderpass;
     framebuffers = std::move(rhs.framebuffers);
@@ -194,6 +202,9 @@ namespace SHADE
     ptrToResources = std::move(rhs.ptrToResources);
     pipelineLibrary = std::move(rhs.pipelineLibrary);
     batcher = std::move(rhs.batcher);
+    spDescs = std::move(rhs.spDescs);
+    spDeps = std::move(rhs.spDeps);
+
 
     rhs.renderpass = {};
 
@@ -224,10 +235,10 @@ namespace SHADE
     }
 
     // Add subpass to container and create mapping for it
-    subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
+    subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
     subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
     Handle<SHSubpass> subpass = subpasses.back();
-    subpass->Init(resourceManager);
+    subpass->Init(*resourceManager);
 
     // Register the SuperBatch
     batcher.RegisterSuperBatch(subpass->GetSuperBatch());
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
index 28527a92..77861108 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
@@ -9,6 +9,7 @@
 #include "SH_API.h"
 #include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
 #include "Graphics/MiddleEnd/Batching/SHBatcher.h"
+#include "SHAttachmentDescInitParams.h"
 
 namespace SHADE
 {
@@ -25,7 +26,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                              */
     /*-----------------------------------------------------------------------*/
-    ResourceManager& resourceManager;
+    std::shared_ptr<ResourceManager> resourceManager;
 
     //! For Vulkan object creation
     Handle<SHVkLogicalDevice> logicalDeviceHdl;
@@ -87,7 +88,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
+    SHRenderGraphNode(std::shared_ptr<ResourceManager> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
     SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
     SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
 
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
index bcd1dc9f..adf3b6cd 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
@@ -45,10 +45,10 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
+  SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
     : logicalDevice {logicalDevice}
     , swapchain{ swapchain }
-    , resourceType{ type }
+    , resourceTypeFlags{ }
     , resourceFormat{ format }
     , images{}
     , imageViews{}
@@ -58,52 +58,10 @@ namespace SHADE
     , resourceName{ name }
   {
     // If the resource type is an arbitrary image and not swapchain image
-    if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
+    if (typeFlags.size() == 1 && *typeFlags.begin() == SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)
     {
-      imageAspectFlags = vk::ImageAspectFlags{};
-      usage = usageFlags;
+      resourceTypeFlags |= static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT);
 
-      // Check the resource type and set image usage flags and image aspect flags accordingly
-      switch (resourceType)
-      {
-      case SH_ATT_DESC_TYPE::COLOR:
-        usage |= vk::ImageUsageFlagBits::eColorAttachment;
-        imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
-        break;
-      case SH_ATT_DESC_TYPE::DEPTH:
-        usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
-        imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
-        break;
-      case SH_ATT_DESC_TYPE::STENCIL:
-        usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
-        imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
-        break;
-      case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
-        usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
-        imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
-        break;
-      }
-
-      // The resource is not a swapchain image, just use the first slot of the vector 
-      images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
-
-      // prepare image view details
-      SHImageViewDetails viewDetails
-      {
-        .viewType = vk::ImageViewType::e2D,
-        .format = images[0]->GetImageFormat(),
-        .imageAspectFlags = imageAspectFlags,
-        .baseMipLevel = 0,
-        .mipLevelCount = mipLevels,
-        .baseArrayLayer = 0,
-        .layerCount = 1,
-      };
-
-      // just 1 image view created
-      imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
-    }
-    else // if swapchain image resource
-    {
       // Prepare image view details
       SHImageViewDetails viewDetails
       {
@@ -126,6 +84,65 @@ namespace SHADE
         imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
       }
     }
+    else // if swapchain image resource
+    {
+      imageAspectFlags = vk::ImageAspectFlags{};
+      usage = usageFlags;
+
+      for (auto& type : typeFlags)
+      {
+        // store the flags
+        resourceTypeFlags |= static_cast<uint32_t>(type);
+
+        // Check the resource type and set image usage flags and image aspect flags accordingly
+        switch (type)
+        {
+        case SH_ATT_DESC_TYPE_FLAGS::COLOR:
+          usage |= vk::ImageUsageFlagBits::eColorAttachment;
+          imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
+          break;
+        case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
+          usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
+          imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
+          break;
+        case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
+          usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
+          imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
+          break;
+        case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
+          usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
+          imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
+          break;
+        case SH_ATT_DESC_TYPE_FLAGS::INPUT:
+          usage |= vk::ImageUsageFlagBits::eInputAttachment;
+          usage |= vk::ImageUsageFlagBits::eSampled;
+          break;
+        case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
+          {
+            SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
+            return;
+          }
+        }
+      }
+
+      // The resource is not a swapchain image, just use the first slot of the vector 
+      images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
+
+      // prepare image view details
+      SHImageViewDetails viewDetails
+      {
+        .viewType = vk::ImageViewType::e2D,
+        .format = images[0]->GetImageFormat(),
+        .imageAspectFlags = imageAspectFlags,
+        .baseMipLevel = 0,
+        .mipLevelCount = mipLevels,
+        .baseArrayLayer = 0,
+        .layerCount = 1,
+      };
+
+      // just 1 image view created
+      imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
+    }
   }
 
   /***************************************************************************/
@@ -141,7 +158,7 @@ namespace SHADE
   /***************************************************************************/
   SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
     : resourceName{ std::move(rhs.resourceName) }
-    , resourceType{ std::move(rhs.resourceType) }
+    , resourceTypeFlags{ std::move(rhs.resourceTypeFlags) }
     , images{ std::move(rhs.images) }
     , imageViews{ std::move(rhs.imageViews) }
     , resourceFormat{ std::move(rhs.resourceFormat) }
@@ -149,6 +166,7 @@ namespace SHADE
     , height{ rhs.height }
     , mipLevels{ rhs.mipLevels }
     , imageAspectFlags{ rhs.imageAspectFlags }
+    , swapchain {rhs.swapchain}
   {
 
   }
@@ -172,7 +190,7 @@ namespace SHADE
       return *this;
 
     resourceName = std::move(rhs.resourceName);
-    resourceType = std::move(rhs.resourceType);
+    resourceTypeFlags = std::move(rhs.resourceTypeFlags);
     images = std::move(rhs.images);
     imageViews = std::move(rhs.imageViews);
     resourceFormat = std::move(rhs.resourceFormat);
@@ -180,6 +198,7 @@ namespace SHADE
     height = rhs.height;
     mipLevels = rhs.mipLevels;
     imageAspectFlags = rhs.imageAspectFlags;
+    swapchain = rhs.swapchain;
 
     return *this;
   }
@@ -202,7 +221,7 @@ namespace SHADE
     width = newWidth;
     height = newHeight;
 
-    if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
+    if ((resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0)
     {
       // prepare image view details
       SHImageViewDetails viewDetails
@@ -299,4 +318,9 @@ namespace SHADE
     return height;
   }
 
+  Handle<SHVkImageView> SHRenderGraphResource::GetImageView(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
+  {
+    return imageViews [index];
+  }
+
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
index 66f0677b..efaf9bf5 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
@@ -16,6 +16,8 @@ namespace SHADE
   class SHVkCommandBuffer;
   class SHVkBuffer;
 
+  static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
+
   class SH_API SHRenderGraphResource
   {
   private:
@@ -32,7 +34,7 @@ namespace SHADE
     std::string resourceName;
 
     //! Used for initializing image layouts
-    SH_ATT_DESC_TYPE resourceType;
+    SHRenderGraphResourceFlags resourceTypeFlags;
 
     //! The resource itself (this is a vector because if the resource happens
     //! to be a swapchain image, then we need however many frames in flight). 
@@ -67,7 +69,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
+    SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
     SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
     SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
     ~SHRenderGraphResource(void) noexcept;
@@ -82,9 +84,10 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
     /*-----------------------------------------------------------------------*/
-    vk::Format GetResourceFormat (void) const noexcept;
-    uint32_t   GetWidth          (void) const noexcept;
-    uint32_t   GetHeight         (void) const noexcept;
+    vk::Format            GetResourceFormat (void) const noexcept;
+    uint32_t              GetWidth          (void) const noexcept;
+    uint32_t              GetHeight         (void) const noexcept;
+    Handle<SHVkImageView> GetImageView      (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
 
     friend class SHRenderGraphNode;
     friend class SHRenderGraph;
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
index abd3a7be..ffbe4ff0 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
@@ -23,7 +23,7 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHSubpass::SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
+  SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
     : resourceAttachmentMapping{ mapping }
     , ptrToResources{ resources }
     , parentNode{ parent }
@@ -55,6 +55,8 @@ namespace SHADE
     , inputReferences{ std::move(rhs.inputReferences) }
     , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
     , ptrToResources{ rhs.ptrToResources }
+    , descriptorSetLayout{ rhs.descriptorSetLayout }
+    , exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) }
   {
 
   }
@@ -83,6 +85,8 @@ namespace SHADE
     inputReferences = std::move(rhs.inputReferences);
     resourceAttachmentMapping = rhs.resourceAttachmentMapping;
     ptrToResources = rhs.ptrToResources;
+    descriptorSetLayout = rhs.descriptorSetLayout;
+    exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
 
     return *this;
   }
@@ -120,18 +124,18 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
+  void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType) noexcept
   {
     vk::ImageLayout imageLayout;
     switch (attachmentDescriptionType)
     {
-    case SH_ATT_DESC_TYPE::DEPTH:
+    case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
       imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
       break;
-    case SH_ATT_DESC_TYPE::STENCIL:
+    case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
       imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
       break;
-    case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
+    case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
       imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
       break;
     default:
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
index aba282b9..c567a897 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
@@ -62,7 +62,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
+    SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
     SHSubpass(SHSubpass&& rhs) noexcept;
     SHSubpass& operator=(SHSubpass&& rhs) noexcept;
 
@@ -71,7 +71,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     // Preparation functions
     void AddColorOutput(std::string resourceToReference) noexcept;
-    void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept;
+    void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
     void AddInput(std::string resourceToReference) noexcept;
 
     // Runtime functions
diff --git a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp
index fee23f13..74128ec8 100644
--- a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp
+++ b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp
@@ -253,7 +253,8 @@ namespace SHADE
 
   SHVkRenderpass::~SHVkRenderpass(void) noexcept
   {
-    logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr);
+    if (vkRenderpass)
+      logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr);
   }
 
 
diff --git a/SHADE_Engine/src/Graphics/SHVulkanDefines.h b/SHADE_Engine/src/Graphics/SHVulkanDefines.h
index 1cbcae0f..a0a6d57c 100644
--- a/SHADE_Engine/src/Graphics/SHVulkanDefines.h
+++ b/SHADE_Engine/src/Graphics/SHVulkanDefines.h
@@ -12,6 +12,7 @@ namespace SHADE
   using BindingAndSetHash = uint64_t;
   using SetIndex = uint32_t;
   using SHSubPassIndex = uint32_t;
+  using SHRenderGraphResourceFlags = uint32_t;
 
 }
 
diff --git a/SHADE_Engine/src/Resource/SparseSet.h b/SHADE_Engine/src/Resource/SparseSet.h
index 8a3f9c6e..fb4a8311 100644
--- a/SHADE_Engine/src/Resource/SparseSet.h
+++ b/SHADE_Engine/src/Resource/SparseSet.h
@@ -59,9 +59,9 @@ namespace SHADE
         SparseSet();
         ~SparseSet() = default;
 
-        // Disallow moving or copying
-        SparseSet(const SparseSet&) = delete;
-        SparseSet(SparseSet&&) = delete;
+        //// Disallow moving or copying
+        //SparseSet(const SparseSet&) = delete;
+        //SparseSet(SparseSet&&) = delete;
 
         /*-----------------------------------------------------------------------------*/
         /* Usage Functions                                                             */
diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp
index 65f445a6..d7a090a4 100644
--- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp
+++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp
@@ -115,7 +115,7 @@ namespace SHADE
   /*---------------------------------------------------------------------------------*/
   /* Script Serialisation Functions                                                  */
   /*---------------------------------------------------------------------------------*/
-  std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const
+  std::string SHScriptEngine::SerialiseScripts(EntityID entity) const
   {
     // Create buffer needed to store serialised script data
     constexpr int BUFFER_SIZE = 10240;
@@ -124,7 +124,7 @@ namespace SHADE
 
     // Attempt to serialise the script
     std::string result;
-    if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE))
+    if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE))
     {
       result = std::string(buffer.get());
     }
@@ -140,9 +140,9 @@ namespace SHADE
   /*-----------------------------------------------------------------------------------*/
   /* Script Serialisation Functions                                                    */
   /*-----------------------------------------------------------------------------------*/
-  void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const
+  void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const
   {
-    csScriptDeserialise(entity.GetEID(), yaml.c_str());
+    csScriptDeserialise(entity, yaml.c_str());
   }
 
   /*-----------------------------------------------------------------------------------*/
diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h
index 239d6b90..60723425 100644
--- a/SHADE_Engine/src/Scripting/SHScriptEngine.h
+++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h
@@ -148,7 +148,7 @@ namespace SHADE
     /// <returns>
     /// String that represents the set of scripts attached to the specified Entity.
     /// </returns>
-    std::string SerialiseScripts(const SHEntity& entity) const;
+    std::string SerialiseScripts(EntityID entity) const;
     /// <summary>
     /// Loads the specified JSON string and creates a Script for the specified Entity
     /// based on the specified JSON string.
@@ -157,7 +157,7 @@ namespace SHADE
     /// <param name="yaml">
     /// The YAML string that represents the Script to load into the Entity.
     /// </param>
-    void DeserialiseScript(const SHEntity& entity, const std::string& yaml) const;
+    void DeserialiseScript(EntityID entity, const std::string& yaml) const;
 
     /*-----------------------------------------------------------------------------*/
     /* Script Editor Functions                                                     */
diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp
new file mode 100644
index 00000000..e259fbbc
--- /dev/null
+++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp
@@ -0,0 +1,220 @@
+#include "SHpch.h"
+#include "SHSerializationHelper.hpp"
+#include "SHSerialization.h"
+
+#include <yaml-cpp/yaml.h>
+
+#include "ECS_Base/Managers/SHEntityManager.h"
+#include "Scene/SHSceneManager.h"
+#include "Tools/SHException.h"
+#include "Assets/SHAssetManager.h"
+#include <fstream>
+
+#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
+#include "Math/Transform/SHTransformComponent.h"
+#include "Physics/Components/SHRigidBodyComponent.h"
+
+namespace SHADE
+{
+  void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path)
+  {
+    YAML::Emitter out;
+    SerializeSceneToEmitter(out);
+    std::ofstream file(path.c_str());
+    if (file.good())
+    {
+      file << out.c_str();
+      file.close();
+    }
+  }
+
+  std::string SHSerialization::SerializeSceneToString()
+  {
+    YAML::Emitter out;
+    SerializeSceneToEmitter(out);
+    return std::basic_string<char>(out.c_str());
+  }
+
+  void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out)
+  {
+    auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
+    auto root = sceneGraph.GetRoot();
+
+    SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node.");
+
+    auto const& children = root->GetChildren();
+    out << YAML::BeginSeq;
+
+    auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
+    sceneGraph.Traverse(pred);
+    //out << SerializeEntityToNode(child);
+
+    out << YAML::EndSeq;
+  }
+
+  static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
+  {
+    if (!node[EIDNode])
+      return;
+    EntityID eid = node[EIDNode].as<EntityID>();
+    std::string name = "Default";
+    if (node[EntityNameNode])
+      name = node[EntityNameNode].as<std::string>();
+    //Compile component IDs
+    const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
+    eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
+    createdEntities.push_back(eid);
+    if (node[NumberOfChildrenNode])
+    {
+      if(const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
+      {
+        ++it;
+        for (int i = 0; i < numOfChildren; ++i)
+        {
+          DeserializeEntity(it, (*it), createdEntities, eid);
+          if((i + 1) < numOfChildren)
+            ++it;
+        }
+      }
+    }
+  }
+
+  void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
+  {
+    //TODO:Shift to using XQ's FileIO
+    std::ifstream iFile;
+    iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+    std::string fileContent = "";
+
+    try
+    {
+      // Open file
+      // Read file's buffer contents into streams
+      iFile.open(path);
+      std::stringstream fileStream;
+      fileStream << iFile.rdbuf();
+
+      fileContent = fileStream.str();
+
+      // Close file handler
+      iFile.close();
+    }
+    catch (std::ifstream::failure e)
+    {
+      SHLOG_ERROR("Could not read file");
+    }
+    YAML::Node entities = YAML::Load(fileContent);
+    std::vector<EntityID> createdEntities{};
+
+    //Create Entities
+    for (auto it = entities.begin(); it != entities.end(); ++it)
+    {
+      DeserializeEntity(it, (*it), createdEntities);
+    }
+
+    //Initialize Entity
+    auto entityVecIt = createdEntities.begin();
+    for (auto it = entities.begin(); it != entities.end(); ++it)
+    {
+      InitializeEntity(*it, *entityVecIt++);
+    }
+  }
+
+  void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
+  {
+    out << SerializeEntityToNode(entityNode);
+    auto const& children = entityNode->GetChildren();
+    for(auto const& child : children)
+    {
+      EmitEntity(child, out);
+    }
+  }
+
+  std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities)
+  {
+    YAML::Emitter out;
+    YAML::Node node;
+    auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
+    for (auto const& eid : entities)
+    {
+      auto entityNode = sceneGraph.GetNode(eid);
+      EmitEntity(entityNode, out);
+    }
+    return std::basic_string<char>(out.c_str());
+  }
+
+  void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
+  {
+  }
+
+  YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
+  {
+    YAML::Node node;
+    auto eid = sceneNode->GetEntityID();
+    auto entity = SHEntityManager::GetEntityByID(eid);
+    if (!sceneNode || !entity)
+    {
+      node = YAML::Null;
+      return node;
+    }
+    node.SetStyle(YAML::EmitterStyle::Block);
+    node[EIDNode] = eid;
+    node[EntityNameNode] = entity->name;
+    node[IsActiveNode] = sceneNode->IsActive();
+    auto const& children = sceneNode->GetChildren();
+    node[NumberOfChildrenNode] = children.size();
+
+    YAML::Node components;
+
+    if (const auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
+    {
+      components[rttr::type::get<SHTransformComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform);
+    }
+    if (const auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(eid))
+    {
+      components[rttr::type::get<SHRenderable>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable);
+    }
+    if (const auto rigidbody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
+    {
+      components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
+    }
+    node[ComponentsNode] = components;
+    return node;
+  }
+
+  template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+  std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
+  {
+    if (componentNode[rttr::type::get<ComponentType>().get_name().data()])
+      return { SHFamilyID<SHComponent>::GetID<ComponentType>() };
+    else
+      return std::nullopt;
+  }
+
+  std::vector<ComponentTypeID> SHSerialization::GetComponentIDList(YAML::Node const& componentsNode)
+  {
+    std::vector<ComponentTypeID> componentIDList;
+
+    auto id = GetComponentID<SHTransformComponent>(componentsNode);
+    if (id.has_value())
+      componentIDList.push_back(id.value());
+
+    id = GetComponentID<SHRenderable>(componentsNode);
+    if (id.has_value())
+      componentIDList.push_back(id.value());
+
+    id = GetComponentID<SHRigidBodyComponent>(componentsNode);
+    if (id.has_value())
+      componentIDList.push_back(id.value());
+
+    return componentIDList;
+  }
+
+  void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
+  {
+    auto const componentsNode = entityNode[ComponentsNode];
+    if (!componentsNode)
+      return;
+    SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
+  }
+}
diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h
new file mode 100644
index 00000000..d247de7a
--- /dev/null
+++ b/SHADE_Engine/src/Serialization/SHSerialization.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "SH_API.h"
+#include <string>
+#include <filesystem>
+
+#include <ECS_Base/Components/SHComponent.h>
+
+namespace YAML
+{
+  class Emitter;
+  class Node;
+}
+
+namespace SHADE
+{
+  class SHSceneNode;
+
+  constexpr const char* ComponentsNode = "Components";
+  constexpr const char* EntityNameNode = "Name";
+  constexpr const char* EIDNode = "EID";
+  constexpr const char* IsActiveNode = "IsActive";
+  constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
+
+  struct SH_API SHSerialization
+  {
+    //TODO: change paths to resource ID
+    static void SerializeSceneToFile(std::filesystem::path const& path);
+    static std::string SerializeSceneToString();
+    static void SerializeSceneToEmitter(YAML::Emitter& out);
+    static void DeserializeSceneFromFile(std::filesystem::path const& path);
+    
+    
+    static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
+    static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities);
+    static void SerializeEntityToFile(std::filesystem::path const& path);
+    static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
+
+    static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
+  private:
+    static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
+  };
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp
new file mode 100644
index 00000000..da98c885
--- /dev/null
+++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp
@@ -0,0 +1,204 @@
+#pragma once
+
+#include "ECS_Base/Components/SHComponent.h"
+#include <yaml-cpp/yaml.h>
+
+#include <rttr/registration>
+
+#include "ECS_Base/Managers/SHComponentManager.h"
+#include "Math/Vector/SHVec2.h"
+#include "Math/Vector/SHVec3.h"
+#include "Math/Vector/SHVec4.h"
+
+namespace SHADE
+{
+  struct SHSerializationHelper
+  {
+    template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+    static std::string SerializeComponentToString(ComponentType* component)
+    {
+      return std::string();
+    }
+
+    template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+    static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
+    {
+    }
+
+    static YAML::Node RTTRToNode(const rttr::variant& var)
+    {
+      YAML::Node node;
+      auto varType = var.get_type();
+      if (varType == rttr::type::get<SHVec4>())
+      {
+        node.SetStyle(YAML::EmitterStyle::Flow);
+        node["X"] = var.convert<SHVec4>().x;
+        node["Y"] = var.convert<SHVec4>().y;
+        node["Z"] = var.convert<SHVec4>().z;
+        node["W"] = var.convert<SHVec4>().w;
+      }
+      else if (varType == rttr::type::get<SHVec3>())
+      {
+        node.SetStyle(YAML::EmitterStyle::Flow);
+        node["X"] = var.convert<SHVec3>().x;
+        node["Y"] = var.convert<SHVec3>().y;
+        node["Z"] = var.convert<SHVec3>().z;
+      }
+      else if (varType == rttr::type::get<SHVec2>())
+      {
+        node.SetStyle(YAML::EmitterStyle::Flow);
+        node["X"] = var.convert<SHVec3>().x;
+        node["Y"] = var.convert<SHVec3>().y;
+      }
+      else if (varType.is_arithmetic())
+      {
+        bool ok = false;
+        if (varType == rttr::type::get<bool>())
+          node = var.to_bool();
+        else if (varType == rttr::type::get<int8_t>())
+          node = var.to_int8(&ok);
+        else if (varType == rttr::type::get<int16_t>())
+          node = var.to_int16(&ok);
+        else if (varType == rttr::type::get<int32_t>())
+          node = var.to_int32(&ok);
+        else if (varType == rttr::type::get<int64_t>())
+          node = var.to_int64(&ok);
+        else if (varType == rttr::type::get<uint8_t>())
+          node = var.to_uint8(&ok);
+        else if (varType == rttr::type::get<uint16_t>())
+          node = var.to_uint16(&ok);
+        else if (varType == rttr::type::get<uint32_t>())
+          node = var.to_uint32(&ok);
+        else if (varType == rttr::type::get<uint64_t>())
+          node = var.to_uint64(&ok);
+        else if (varType == rttr::type::get<float>())
+          node = var.to_float(&ok);
+        else if (varType == rttr::type::get<double>())
+          node = var.to_double(&ok);
+        //else if (varType == rttr::type::get<char>()) //same as uint8_t
+        //    node = var.to_uint8();
+      }
+      else if (varType.is_enumeration())
+      {
+        bool ok = false;
+        auto result = var.to_string(&ok);
+        if (ok)
+        {
+          node = var.to_string();
+        }
+        else
+        {
+          ok = false;
+          auto value = var.to_uint64(&ok);
+          if (ok)
+            node = value;
+          else
+            node = YAML::Null;
+        }
+      }
+      else
+      {
+        auto properties = var.get_type().get_properties();
+        for (auto property : properties)
+        {
+          node[property.get_name().data()] = RTTRToNode(property.get_value(var));
+        }
+      }
+      return node;
+    }
+
+    template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+    static YAML::Node SerializeComponentToNode(ComponentType* component)
+    {
+      YAML::Node node{};
+      if (!component)
+        return node;
+
+      auto componentType = rttr::type::get<ComponentType>();
+      node = RTTRToNode(*component);
+
+      return node;
+    }
+
+    template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+    static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode)
+    {
+      auto propType = prop.get_type();
+      if (propType == rttr::type::get<SHVec4>())
+      {
+        SHVec4 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>(), propertyNode["W"].as<float>() };
+        prop.set_value(component, vec);
+      }
+      else if (propType == rttr::type::get<SHVec3>())
+      {
+        SHVec3 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>() };
+        prop.set_value(component, vec);
+      }
+      else if (propType == rttr::type::get<SHVec2>())
+      {
+        SHVec2 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>() };
+        prop.set_value(component, vec);
+      }
+      else if (propType.is_arithmetic())
+      {
+        bool ok = false;
+        if (propType == rttr::type::get<bool>())
+          prop.set_value(component, propertyNode.as<bool>());
+        else if (propType == rttr::type::get<int8_t>())
+          prop.set_value(component, propertyNode.as<int8_t>());
+        else if (propType == rttr::type::get<int16_t>())
+          prop.set_value(component, propertyNode.as<int16_t>());
+        else if (propType == rttr::type::get<int32_t>())
+          prop.set_value(component, propertyNode.as<int32_t>());
+        else if (propType == rttr::type::get<int64_t>())
+          prop.set_value(component, propertyNode.as<int64_t>());
+        else if (propType == rttr::type::get<uint8_t>())
+          prop.set_value(component, propertyNode.as<uint8_t>());
+        else if (propType == rttr::type::get<uint16_t>())
+          prop.set_value(component, propertyNode.as<uint16_t>());
+        else if (propType == rttr::type::get<uint32_t>())
+          prop.set_value(component, propertyNode.as<uint32_t>());
+        else if (propType == rttr::type::get<uint64_t>())
+          prop.set_value(component, propertyNode.as<uint64_t>());
+        else if (propType == rttr::type::get<float>())
+          prop.set_value(component, propertyNode.as<float>());
+        else if (propType == rttr::type::get<double>())
+          prop.set_value(component, propertyNode.as<double>());
+      }
+      else if (propType.is_enumeration())
+      {
+        auto enumAlign = prop.get_enumeration();
+        prop.set_value(component, enumAlign.name_to_value(propertyNode.as<std::string>()));
+      }
+      else
+      {
+        auto properties = propType.get_properties();
+        for (auto property : properties)
+        {
+          InitializeProperty(component, property, propertyNode[property.get_name().data()]);
+        }
+      }
+    }
+
+    template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
+    static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
+    {
+      auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
+      if (componentsNode.IsNull() && !component)
+        return;
+      auto rttrType = rttr::type::get<ComponentType>();
+      auto componentNode = componentsNode[rttrType.get_name().data()];
+      if (componentsNode.IsNull())
+        return;
+      auto properties = rttrType.get_properties();
+      for (auto const& prop : properties)
+      {
+        if (componentNode[prop.get_name().data()])
+        {
+          InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
+        }
+      }
+    }
+
+  };
+}
diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx
index 735f8c2c..8d105fce 100644
--- a/SHADE_Managed/src/Editor/Editor.cxx
+++ b/SHADE_Managed/src/Editor/Editor.cxx
@@ -29,6 +29,7 @@ of DigiPen Institute of Technology is prohibited.
 #include "Editor/IconsMaterialDesign.h"
 #include "Editor/Command/SHCommandManager.h"
 #include "Editor/Command/SHCommand.hpp"
+#include "TooltipAttribute.hxx"
 
 // Using Directives
 using namespace System;
@@ -48,17 +49,17 @@ using namespace System::Collections::Generic;
 /// <param name="MANAGED_TYPE">The managed type of the object to edit.</param>
 /// <param name="NATIVE_TYPE">The native type of the object to edit.</param>
 /// <param name="FUNC">The SHEditorUI:: function to use for editing.</param>
-#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC)                  \
-(field->FieldType == MANAGED_TYPE::typeid)                             \
-{                                                                      \
-    NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
-    NATIVE_TYPE oldVal = val;                                          \
-    if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val))         \
-    {                                                                  \
-        field->SetValue(object, val);                                  \
-        registerUndoAction(object, field, val, oldVal);                \
-    }                                                                  \
-}                                                                      \
+#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC)                     \
+(field->FieldType == MANAGED_TYPE::typeid)                                \
+{                                                                         \
+    NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object));    \
+    NATIVE_TYPE oldVal = val;                                             \
+    if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered))\
+    {                                                                     \
+        field->SetValue(object, val);                                     \
+        registerUndoAction(object, field, val, oldVal);                   \
+    }                                                                     \
+}                                                                         \
 /// <summary>
 /// Macro expansion that is used in renderFieldInInspector() to check the type of a field
 /// named "field" against the specified type and if it matches, retrieves the value of
@@ -76,7 +77,7 @@ using namespace System::Collections::Generic;
 {                                                                                          \
     NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
     NATIVE_TYPE oldVal = val;                                                              \
-    if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val))                             \
+    if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered))                 \
     {                                                                                      \
         field->SetValue(object, Convert::ToCLI(val));                                      \
         registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));    \
@@ -196,6 +197,8 @@ namespace SHADE
     }
     void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object)
     {
+        bool isHovered = false;
+
         if      RENDER_FIELD       (Int16,   int,             InputInt)
         else if RENDER_FIELD       (Int32,   int,             InputInt)
         else if RENDER_FIELD       (Int64,   int,             InputInt)
@@ -244,6 +247,15 @@ namespace SHADE
                 registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
             }
         }
+
+        // Check if the field has a specific attribute
+        TooltipAttribute^ toolTip = hasAttribute<TooltipAttribute^>(field);
+        if (toolTip && isHovered)
+        {
+            SHEditorUI::BeginTooltip();
+            SHEditorUI::Text(Convert::ToNative(toolTip->Description));
+            SHEditorUI::EndTooltip();
+        }
     }
 
     void Editor::renderScriptContextMenu(Entity entity, Script^ script)
@@ -274,4 +286,24 @@ namespace SHADE
         SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCLICommand>()));
     }
 
+    generic<typename Attribute>
+    Attribute Editor::hasAttribute(System::Reflection::FieldInfo^ field)
+    {
+        array<System::Object^>^ attributes = field->GetCustomAttributes(true);
+        for each (System::Object^ attrib in attributes)
+        {
+            try
+            {
+                Attribute attribute = safe_cast<Attribute>(attrib);
+                if (attribute != nullptr)
+                    return attribute;
+            }
+            catch (System::InvalidCastException^)
+            {
+                continue;
+            }
+        }
+        // Failed to find
+        return Attribute{};
+    }
 }
diff --git a/SHADE_Managed/src/Editor/Editor.hxx b/SHADE_Managed/src/Editor/Editor.hxx
index c4800645..6b59589a 100644
--- a/SHADE_Managed/src/Editor/Editor.hxx
+++ b/SHADE_Managed/src/Editor/Editor.hxx
@@ -23,7 +23,7 @@ namespace SHADE
     /// <summary>
     /// Static class for Editor-related functions
     /// </summary>
-    public ref class Editor abstract sealed
+    private ref class Editor abstract sealed
     {
       public:
         /*-----------------------------------------------------------------------------*/
@@ -48,7 +48,13 @@ namespace SHADE
         /*-----------------------------------------------------------------------------*/
         /* UndoRedoStack Functions                                                     */
         /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Undoes the last script inspector change if there is any.
+        /// </summary>
         static void Undo();
+        /// <summary>
+        /// Redoes the last script inspector change if there is any.
+        /// </summary>
         static void Redo();
 
     private:
@@ -86,5 +92,7 @@ namespace SHADE
         /// <param name="script">The Script to render the inspector for.</param>
         static void renderScriptContextMenu(Entity entity, Script^ script);
         static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
+        generic<typename Attribute> where Attribute : System::Attribute
+        static Attribute hasAttribute(System::Reflection::FieldInfo^ field);
     };
 }
diff --git a/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx b/SHADE_Managed/src/Editor/TooltipAttribute.cxx
similarity index 54%
rename from SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx
rename to SHADE_Managed/src/Editor/TooltipAttribute.cxx
index c371d200..8d5a5d55 100644
--- a/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx
+++ b/SHADE_Managed/src/Editor/TooltipAttribute.cxx
@@ -1,27 +1,34 @@
 /************************************************************************************//*!
-\file           SerializeFieldAttribute.cxx
+\file           TooltipAttribute.cxx
 \author         Tng Kah Wei, kahwei.tng, 390009620
 \par            email: kahwei.tng\@digipen.edu
-\date           Nov 5, 2021
-\brief          Contains the definition of the functions of the managed SerializeField
-                Attribute class.
+\date           Oct 18, 2022
+\brief          Contains the definition of the functions of the managed Tooltip Attribute
+                class.
 
                 Note: This file is written in C++17/CLI.
- 
-Copyright (C) 2021 DigiPen Institute of Technology.
-Reproduction or disclosure of this file or its contents without the prior written consent 
+
+Copyright (C) 2022 DigiPen Institute of Technology.
+Reproduction or disclosure of this file or its contents without the prior written consent
 of DigiPen Institute of Technology is prohibited.
 *//*************************************************************************************/
-// Precompiled Headers
 #include "SHpch.h"
-// Primary Header
-#include "SerializeFieldAttribute.hxx"
+#include "TooltipAttribute.hxx"
 
 namespace SHADE
 {
+    /*---------------------------------------------------------------------------------*/
+    /* Properties                                                                      */
+    /*---------------------------------------------------------------------------------*/
+    System::String^ TooltipAttribute::Description::get()
+    {
+        return desc;
+    }
+
     /*---------------------------------------------------------------------------------*/
     /* Constructors                                                                    */
     /*---------------------------------------------------------------------------------*/
-    SerializeField::SerializeField()
+    TooltipAttribute::TooltipAttribute(System::String^ description)
+    : desc { description }
     {}
 }
diff --git a/SHADE_Managed/src/Editor/TooltipAttribute.hxx b/SHADE_Managed/src/Editor/TooltipAttribute.hxx
new file mode 100644
index 00000000..e7cd168c
--- /dev/null
+++ b/SHADE_Managed/src/Editor/TooltipAttribute.hxx
@@ -0,0 +1,53 @@
+/************************************************************************************//*!
+\file           TooltipAttribute.hxx
+\author         Tng Kah Wei, kahwei.tng, 390009620
+\par            email: kahwei.tng\@digipen.edu
+\date           Oct 18, 2022
+\brief          Contains the definition of the managed Tooltip Attribute class with
+                the declaration of functions for working with it.
+
+                Note: This file is written in C++17/CLI.
+
+Copyright (C) 2022 DigiPen Institute of Technology.
+Reproduction or disclosure of this file or its contents without the prior written consent
+of DigiPen Institute of Technology is prohibited.
+*//*************************************************************************************/
+#pragma once
+
+namespace SHADE
+{
+    /// <summary>
+    /// Simple attribute to mark that a field in a Script should be serialised.
+    /// </summary>
+    [System::AttributeUsage(System::AttributeTargets::Field)]
+    public ref class TooltipAttribute : public System::Attribute
+    {
+      public:
+        /*-----------------------------------------------------------------------------*/
+        /* Properties                                                                  */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Description that is to be shown in the Tooltip.
+        /// </summary>
+        property System::String^ Description
+        {
+            System::String^ get();
+        }
+
+        /*-----------------------------------------------------------------------------*/
+        /* Constructors                                                                */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Constructor for a Tooltip attribute that fills in the description.
+        /// </summary>
+        /// <param name="description">Text to be shown when a field is hovered.</param>
+        TooltipAttribute(System::String^ description);
+
+      private:
+        /*-----------------------------------------------------------------------------*/
+        /* Data Members                                                                */
+        /*-----------------------------------------------------------------------------*/
+        System::String^ desc;
+    };
+}
+
diff --git a/SHADE_Managed/src/Input/Input.cxx b/SHADE_Managed/src/Input/Input.cxx
new file mode 100644
index 00000000..0a386f3a
--- /dev/null
+++ b/SHADE_Managed/src/Input/Input.cxx
@@ -0,0 +1,102 @@
+/************************************************************************************//*!
+\file           Input.cxx
+\author         Tng Kah Wei, kahwei.tng, 390009620
+\par            email: kahwei.tng\@digipen.edu
+\date           Oct 16, 2022
+\brief          Contains the definition of the managed Input static class.
+
+                Note: This file is written in C++17/CLI.
+ 
+Copyright (C) 2022 DigiPen Institute of Technology.
+Reproduction or disclosure of this file or its contents without the prior written consent 
+of DigiPen Institute of Technology is prohibited.
+*//*************************************************************************************/
+#include "SHpch.h"
+#include "Input.hxx"
+#include "Utility/Convert.hxx"
+
+namespace SHADE
+{
+    /*---------------------------------------------------------------------------------*/
+    /* Properties                                                                      */
+    /*---------------------------------------------------------------------------------*/
+    Vector3 Input::MousePosition::get()
+    {
+        int x, y;
+        SHInputManager::GetMouseWindowPosition(&x, &y);
+        return Vector3(static_cast<float>(x), static_cast<float>(y), 0.0f);
+    }
+    int Input::MouseScrollDelta::get()
+    {
+        return SHInputManager::GetMouseWheelVerticalDelta();
+    }
+
+    /*---------------------------------------------------------------------------------*/
+    /* Usage Functions                                                                 */
+    /*---------------------------------------------------------------------------------*/
+    bool Input::GetKey(KeyCode key)
+    {
+        return SHInputManager::GetKey(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    bool Input::GetKeyDown(KeyCode key)
+    {
+        return SHInputManager::GetKeyDown(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    bool Input::GetKeyUp(KeyCode key)
+    {
+        return SHInputManager::GetKeyUp(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    bool Input::GetMouseButton(MouseCode mouseButton)
+    {
+        return SHInputManager::GetKey(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
+    }
+
+    bool Input::GetMouseButtonDown(MouseCode mouseButton)
+    {
+        return SHInputManager::GetKeyDown(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
+    }
+
+    bool Input::GetMouseButtonUp(MouseCode mouseButton)
+    {
+        return SHInputManager::GetKeyUp(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
+    }
+
+    /*---------------------------------------------------------------------------------*/
+    /* Cursor Functions                                                                */
+    /*---------------------------------------------------------------------------------*/
+    void Input::SetMousePosition(Vector2 pos)
+    {
+        SHInputManager::SetMouseWindowPosition
+        (
+            static_cast<int>(pos.x),
+            static_cast<int>(pos.y)
+        );
+    }
+
+    /*---------------------------------------------------------------------------------*/
+    /* Time Functions                                                                  */
+    /*---------------------------------------------------------------------------------*/
+    double Input::GetKeyHeldTime(KeyCode key)
+    {
+        return SHInputManager::GetKeyHeldTime(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    double Input::GetKeyReleasedTime(KeyCode key)
+    {
+        return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    double Input::GetMouseHeldTime(MouseCode key)
+    {
+        return SHInputManager::GetKeyHeldTime(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+    double Input::GetMouseReleasedTime(MouseCode key)
+    {
+        return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
+    }
+
+}
\ No newline at end of file
diff --git a/SHADE_Managed/src/Input/Input.hxx b/SHADE_Managed/src/Input/Input.hxx
new file mode 100644
index 00000000..f281e4c8
--- /dev/null
+++ b/SHADE_Managed/src/Input/Input.hxx
@@ -0,0 +1,325 @@
+/************************************************************************************//*!
+\file           Input.hxx
+\author         Tng Kah Wei, kahwei.tng, 390009620
+\par            email: kahwei.tng\@digipen.edu
+\date           Oct 16, 2022
+\brief          Contains the definition of the managed Input static class.
+
+                Note: This file is written in C++17/CLI.
+ 
+Copyright (C) 2022 DigiPen Institute of Technology.
+Reproduction or disclosure of this file or its contents without the prior written consent 
+of DigiPen Institute of Technology is prohibited.
+*//*************************************************************************************/
+#pragma once
+
+#include "Input/SHInputManager.h"
+#include "Math/Vector2.hxx"
+#include "Math/Vector3.hxx"
+
+namespace SHADE
+{
+    /// <summary>
+    /// Static class responsible for providing access to Input-related functionality.
+    /// </summary>
+    public ref class Input abstract sealed
+    {
+      public:
+        /*-----------------------------------------------------------------------------*/
+        /* Type Definitions                                                            */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Represents the available supported keycodes that can be passed into the 
+        /// key-based Input functions.
+        /// </summary>
+        enum class KeyCode : int
+        {
+            Space           = static_cast<int>(SHInputManager::SH_KEYCODE::SPACE),
+            //Apostrophe		= static_cast<int>(SHInputManager::SH_KEYCODE::APOSTROPHE),
+            Comma           = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_COMMA),
+            Minus           = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_MINUS),
+            Period          = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_PERIOD),
+            //Slash           = static_cast<int>(SHInputManager::SH_KEYCODE::SLASH),
+            Key0            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_0),
+            Key1            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_1),
+            Key2            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_2),
+            Key3            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_3),
+            Key4            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_4),
+            Key5            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_5),
+            Key6            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_6),
+            Key7            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_7),
+            Key8            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_8),
+            Key9            = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_9),
+            
+            //Semicolon       = static_cast<int>(SHInputManager::SH_KEYCODE::SEMICOLON),
+            //Equal           = static_cast<int>(SHInputManager::SH_KEYCODE::EQUAL),
+            
+            A               = static_cast<int>(SHInputManager::SH_KEYCODE::A),
+            B               = static_cast<int>(SHInputManager::SH_KEYCODE::B),
+            C               = static_cast<int>(SHInputManager::SH_KEYCODE::C),
+            D               = static_cast<int>(SHInputManager::SH_KEYCODE::D),
+            E               = static_cast<int>(SHInputManager::SH_KEYCODE::E),
+            F               = static_cast<int>(SHInputManager::SH_KEYCODE::F),
+            G               = static_cast<int>(SHInputManager::SH_KEYCODE::G),
+            H               = static_cast<int>(SHInputManager::SH_KEYCODE::H),
+            I               = static_cast<int>(SHInputManager::SH_KEYCODE::I),
+            J               = static_cast<int>(SHInputManager::SH_KEYCODE::J),
+            K               = static_cast<int>(SHInputManager::SH_KEYCODE::K),
+            L               = static_cast<int>(SHInputManager::SH_KEYCODE::L),
+            M               = static_cast<int>(SHInputManager::SH_KEYCODE::M),
+            N               = static_cast<int>(SHInputManager::SH_KEYCODE::N),
+            O               = static_cast<int>(SHInputManager::SH_KEYCODE::O),
+            P               = static_cast<int>(SHInputManager::SH_KEYCODE::P),
+            Q               = static_cast<int>(SHInputManager::SH_KEYCODE::Q),
+            R               = static_cast<int>(SHInputManager::SH_KEYCODE::R),
+            S               = static_cast<int>(SHInputManager::SH_KEYCODE::S),
+            T               = static_cast<int>(SHInputManager::SH_KEYCODE::T),
+            U               = static_cast<int>(SHInputManager::SH_KEYCODE::U),
+            V               = static_cast<int>(SHInputManager::SH_KEYCODE::V),
+            W               = static_cast<int>(SHInputManager::SH_KEYCODE::W),
+            X               = static_cast<int>(SHInputManager::SH_KEYCODE::X),
+            Y               = static_cast<int>(SHInputManager::SH_KEYCODE::Y),
+            Z               = static_cast<int>(SHInputManager::SH_KEYCODE::Z),
+
+            //LeftBracket     = static_cast<int>(SHInputManager::SH_KEYCODE::LEFTBRACKET),
+            //BackSlash       = static_cast<int>(SHInputManager::SH_KEYCODE::BACKSLASH),
+            //RightBracket    = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHTBRACKET),
+            //GraveAccent     = static_cast<int>(SHInputManager::SH_KEYCODE::GRAVEACCENT),
+
+            //WORLD1          = static_cast<int>(SHInputManager::SH_KEYCODE::WORLD1),
+            //WORLD2          = static_cast<int>(SHInputManager::SH_KEYCODE::WORLD2),
+
+            /* Function keys */
+            Escape			= static_cast<int>(SHInputManager::SH_KEYCODE::ESCAPE),
+            Enter			= static_cast<int>(SHInputManager::SH_KEYCODE::ENTER),	
+            Tab				= static_cast<int>(SHInputManager::SH_KEYCODE::TAB),			
+            Backspace		= static_cast<int>(SHInputManager::SH_KEYCODE::BACKSPACE),
+            Insert			= static_cast<int>(SHInputManager::SH_KEYCODE::INSERT),	
+            Delete			= static_cast<int>(SHInputManager::SH_KEYCODE::DEL),			
+            Right			= static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ARROW),		
+            Left			= static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ARROW),		
+            Down			= static_cast<int>(SHInputManager::SH_KEYCODE::DOWN_ARROW),	
+            Up				= static_cast<int>(SHInputManager::SH_KEYCODE::UP_ARROW),	
+            PageUp			= static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_UP),	
+            PageDown		= static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_DOWN),	
+            Home			= static_cast<int>(SHInputManager::SH_KEYCODE::HOME),
+            End				= static_cast<int>(SHInputManager::SH_KEYCODE::END),
+            CapsLock		= static_cast<int>(SHInputManager::SH_KEYCODE::CAPS_LOCK),	
+            ScrollLock		= static_cast<int>(SHInputManager::SH_KEYCODE::SCROLL_LOCK),
+            NumLock			= static_cast<int>(SHInputManager::SH_KEYCODE::NUM_LOCK),		
+            PrintScreen		= static_cast<int>(SHInputManager::SH_KEYCODE::PRINT_SCREEN),	
+            Pause			= static_cast<int>(SHInputManager::SH_KEYCODE::PAUSE),		
+            F1				= static_cast<int>(SHInputManager::SH_KEYCODE::F1),			
+            F2				= static_cast<int>(SHInputManager::SH_KEYCODE::F2),			
+            F3				= static_cast<int>(SHInputManager::SH_KEYCODE::F3),			
+            F4				= static_cast<int>(SHInputManager::SH_KEYCODE::F4),			
+            F5				= static_cast<int>(SHInputManager::SH_KEYCODE::F5),			
+            F6				= static_cast<int>(SHInputManager::SH_KEYCODE::F6),			
+            F7				= static_cast<int>(SHInputManager::SH_KEYCODE::F7),			
+            F8				= static_cast<int>(SHInputManager::SH_KEYCODE::F8),			
+            F9				= static_cast<int>(SHInputManager::SH_KEYCODE::F9),			
+            F10				= static_cast<int>(SHInputManager::SH_KEYCODE::F10),		
+            F11				= static_cast<int>(SHInputManager::SH_KEYCODE::F11),		
+            F12				= static_cast<int>(SHInputManager::SH_KEYCODE::F12),		
+            F13				= static_cast<int>(SHInputManager::SH_KEYCODE::F13),		
+            F14				= static_cast<int>(SHInputManager::SH_KEYCODE::F14),		
+            F15				= static_cast<int>(SHInputManager::SH_KEYCODE::F15),		
+            F16				= static_cast<int>(SHInputManager::SH_KEYCODE::F16),		
+            F17				= static_cast<int>(SHInputManager::SH_KEYCODE::F17),		
+            F18				= static_cast<int>(SHInputManager::SH_KEYCODE::F18),		
+            F19				= static_cast<int>(SHInputManager::SH_KEYCODE::F19),		
+            F20				= static_cast<int>(SHInputManager::SH_KEYCODE::F20),		
+            F21				= static_cast<int>(SHInputManager::SH_KEYCODE::F21),		
+            F22				= static_cast<int>(SHInputManager::SH_KEYCODE::F22),		
+            F23				= static_cast<int>(SHInputManager::SH_KEYCODE::F23),		
+            F24				= static_cast<int>(SHInputManager::SH_KEYCODE::F24),		
+
+            /* Keypad */
+            KeyPad0	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_0),
+            KeyPad1	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_1),
+            KeyPad2	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_2),
+            KeyPad3	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_3),
+            KeyPad4	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_4),
+            KeyPad5	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_5),
+            KeyPad6	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_6),
+            KeyPad7	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_7),
+            KeyPad8	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_8),
+            KeyPad9	        = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_9),
+            //KeyPadDecimal   = static_cast<int>(SHInputManager::SH_KEYCODE::KPDECIMAL),
+            //KeyPadDivide    = static_cast<int>(SHInputManager::SH_KEYCODE::KPDIVIDE),
+            //KeyPadMultiply  = static_cast<int>(SHInputManager::SH_KEYCODE::KPMULTIPLY),
+            //KeyPadSubtract  = static_cast<int>(SHInputManager::SH_KEYCODE::KPSUBTRACT),
+            //KeyPadAdd       = static_cast<int>(SHInputManager::SH_KEYCODE::KPADD),
+            //KeyPadEnter     = static_cast<int>(SHInputManager::SH_KEYCODE::KPENTER),		
+            //KeyPadEqual     = static_cast<int>(SHInputManager::SH_KEYCODE::KEYPAD),	
+
+            Shift           = static_cast<int>(SHInputManager::SH_KEYCODE::SHIFT),
+            LeftControl     = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_CTRL),
+            LeftAlt         = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ALT),
+            LeftSuper       = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_WINDOWS), 
+            RightShift      = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_SHIFT),
+            RightControl    = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_CTRL),
+            RightAlt        = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ALT),
+            RightSuper      = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_WINDOWS),
+
+            /* Gamepad */
+            JoystickA             = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_A),
+            JoystickB             = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_B),
+            JoystickX             = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_X),
+            JoystickY             = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_Y),
+            JoystickLeftBumper    = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFTSHOULDER),
+            JoystickRightBumper   = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHTSHOULDER),
+            JoystickLeftTrigger   = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFTTRIGGER),
+            JoystickRightTrigger  = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHTTRIGGER),
+            JoystickDPadUp        = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_UP),
+            JoystickDPadDown      = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_DOWN),
+            JoystickDPadLeft      = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_LEFT),
+            JoystickDPadRight     = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_RIGHT),
+            JoystickMenu          = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_MENU),
+            JoystickView          = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_VIEW),
+            JoystickLeftStick     = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFT_THUMBSTICK_BUTTON),
+            JoystickRightStick    = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHT_THUMBSTICK_BUTTON),
+
+            /* Unity Gamepad Mappings */
+            JoystickButton0       =  JoystickA,           
+            JoystickButton1       =  JoystickB,          
+            JoystickButton2       =  JoystickX,           
+            JoystickButton3       =  JoystickY,           
+            JoystickButton4       =  JoystickLeftBumper,  
+            JoystickButton5       =  JoystickRightBumper, 
+            JoystickButton6       =  JoystickView,        
+            JoystickButton7       =  JoystickMenu,        
+            JoystickButton8       =  JoystickLeftStick,   
+            JoystickButton9       =  JoystickRightStick  
+
+        };
+        /// <summary>
+        /// Represents the available supported mouse keycodes that can be passed into the 
+        /// mouse-button-based Input functions.
+        /// </summary>
+        enum class MouseCode : int
+        {
+            LeftButton	 = static_cast<int>(SHInputManager::SH_KEYCODE::LMB),
+            RightButton	 = static_cast<int>(SHInputManager::SH_KEYCODE::RMB),
+            MiddleButton = static_cast<int>(SHInputManager::SH_KEYCODE::MMB),
+            Button3	     = static_cast<int>(SHInputManager::SH_KEYCODE::XMB1),
+            Button4	     = static_cast<int>(SHInputManager::SH_KEYCODE::XMB2)
+        };
+
+        /*-----------------------------------------------------------------------------*/
+        /* Properites                                                                  */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Mouse position in screen coordinates relative to the top left of the window.
+        /// This value is a Vector3 for compatibility with functions that have Vector3 
+        /// arguments. The z component of the Vector3 is always 0
+        /// </summary>
+        static property Vector3 MousePosition
+        {
+            Vector3 get();
+        }
+        /// <summary>
+        /// Amnount of vertical mouse scroll in this frame.
+        /// </summary>
+        static property int MouseScrollDelta
+        {
+            int get();
+        }
+
+        /*-----------------------------------------------------------------------------*/
+        /* Usage Functions                                                             */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Checks if a specified key is being held down.
+        /// This will also be true if GetKeyDown() is true.
+        /// </summary>
+        /// <param name="key">KeyCode of the key to check.</param>
+        /// <returns>True while the user holds down the key specified.</returns>
+        static bool GetKey(KeyCode key);
+        /// <summary>
+        /// Checks if a specified key is pressed and was not pressed before.
+        /// </summary>
+        /// <param name="key">KeyCode of the key to check.</param>
+        /// <returns>
+        /// True during the frame the user starts pressing down the key specified.
+        /// </returns>
+        static bool GetKeyDown(KeyCode key);
+        /// <summary>
+        /// Checks if a specified key is no longer pressed pressed and was pressed
+        /// before.
+        /// </summary>
+        /// <param name="key">KeyCode of the key to check.</param>
+        /// <returns>
+        /// True during the frame the user releases the key identified by name.
+        /// </returns>
+        static bool GetKeyUp(KeyCode key);
+        /// <summary>
+        /// Checks if a specified mouse button is being held down.
+        /// This will also be true if GetMouseButtonDown() is true.
+        /// </summary>
+        /// <param name="mouseButton">MouseCode of the mouse button to check.</param>
+        /// <returns>True while the user holds down the mouse button specified.</returns>
+        static bool GetMouseButton(MouseCode mouseButton);
+        /// <summary>
+        /// Checks if a specified mouse button is pressed and was not pressed before.
+        /// </summary>
+        /// <param name="mouseButton">MouseCode of the mouse button to check.</param>
+        /// <returns>
+        /// True during the frame the user pressed the given mouse button.
+        /// </returns>
+        static bool GetMouseButtonDown(MouseCode mouseButton);
+        /// <summary>
+        /// Checks if a specified mouse button is no longer pressed and was pressed
+        /// before.
+        /// </summary>
+        /// <param name="mouseButton">MouseCode of the mouse button to check.</param>
+        /// <returns>
+        /// True during the frame the user releases the given mouse button.
+        /// </returns>
+        static bool GetMouseButtonUp(MouseCode mouseButton);
+        
+        /*-----------------------------------------------------------------------------*/
+        /* Cursor Functions                                                            */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Sets the position of the mouse cursor relative to the top left corner of the
+        /// window.
+        /// </summary>
+        /// <param name="pos">
+        /// Position of the mouse in window pixel coordinates to set.
+        /// </param>
+        static void SetMousePosition(Vector2 pos);
+
+        /*-----------------------------------------------------------------------------*/
+        /* Timing Functions                                                            */
+        /*-----------------------------------------------------------------------------*/
+        /// <summary>
+        /// Retrieves the duration that the specified key has been held or was last held
+        /// for.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns>Time in seconds that the key was held.</returns>
+        static double GetKeyHeldTime(KeyCode key);
+        /// <summary>
+        /// Retrieves the duration that the specified key has not been held or was last
+        /// not been held for.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns>Time in seconds that the key was held.</returns>
+        static double GetKeyReleasedTime(KeyCode key);
+        /// <summary>
+        /// Retrieves the duration that the specified key has been held or was last held
+        /// for.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns>Time in seconds that the key was held.</returns>
+        static double GetMouseHeldTime(MouseCode mouseButton);
+        /// <summary>
+        /// Retrieves the duration that the specified key has not been held or was last
+        /// not been held for.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns>Time in seconds that the key was held.</returns>
+        static double GetMouseReleasedTime(MouseCode mouseButton);
+    };
+}
\ No newline at end of file
diff --git a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx
index 533ded2a..7a7bb83c 100644
--- a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx
+++ b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx
@@ -21,15 +21,6 @@ namespace SHADE
     /// </summary>
     [System::AttributeUsage(System::AttributeTargets::Field)]
     public ref class SerializeField : public System::Attribute
-    {
-      public:
-        /*-----------------------------------------------------------------------------*/
-        /* Constructors                                                                */
-        /*-----------------------------------------------------------------------------*/
-        /// <summary>
-        /// Default Constructor
-        /// </summary>
-        SerializeField();
-    };
+    {};
 }
 
diff --git a/TempScriptsFolder/RaccoonShowcase.cs b/TempScriptsFolder/RaccoonShowcase.cs
index e2d6454d..93ea53eb 100644
--- a/TempScriptsFolder/RaccoonShowcase.cs
+++ b/TempScriptsFolder/RaccoonShowcase.cs
@@ -3,8 +3,12 @@ using System;
 
 public class RaccoonShowcase : Script
 {
-    public double RotateSpeed = 1.0;
-    public Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
+    [SerializeField]
+    [Tooltip("Speed of the rotation in radians per second.")]
+    private double RotateSpeed = 1.0;
+    [SerializeField]
+    [Tooltip("Speed of the scaling in radians per second around each axis.")]
+    private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
     private Transform Transform;
     private double rotation = 0.0;
     private Vector3 scale = Vector3.Zero;
diff --git a/TempScriptsFolder/RaccoonSpin.cs b/TempScriptsFolder/RaccoonSpin.cs
index 7785cfd5..d6ee1c9f 100644
--- a/TempScriptsFolder/RaccoonSpin.cs
+++ b/TempScriptsFolder/RaccoonSpin.cs
@@ -3,7 +3,9 @@ using System;
 
 public class RaccoonSpin : Script
 {
-    public double RotateSpeed = 1.0;
+    [SerializeField]
+    [Tooltip("Speed of the rotation in radians per second.")]
+    private double RotateSpeed = 1.0;
     private double rotation = 0.0;
     private Transform Transform;
     public RaccoonSpin(GameObject gameObj) : base(gameObj) { }
