Просмотр исходного кода

Advanced resource loading WIP stage 1

Marko Pintera 11 лет назад
Родитель
Сommit
eb4de059fc

+ 3 - 0
BansheeCore/BansheeCore.vcxproj

@@ -311,6 +311,8 @@
     <ClInclude Include="Include\BsPlatform.h" />
     <ClInclude Include="Include\BsPlatform.h" />
     <ClInclude Include="Include\BsProfilingManager.h" />
     <ClInclude Include="Include\BsProfilingManager.h" />
     <ClInclude Include="Include\BsQueryManager.h" />
     <ClInclude Include="Include\BsQueryManager.h" />
+    <ClInclude Include="Include\BsSavedResourceData.h" />
+    <ClInclude Include="Include\BsSavedResourceDataRTTI.h" />
     <ClInclude Include="Include\BsResourceListenerManager.h" />
     <ClInclude Include="Include\BsResourceListenerManager.h" />
     <ClInclude Include="Include\BsResourceManifest.h" />
     <ClInclude Include="Include\BsResourceManifest.h" />
     <ClInclude Include="Include\BsResourceManifestRTTI.h" />
     <ClInclude Include="Include\BsResourceManifestRTTI.h" />
@@ -476,6 +478,7 @@
     <ClCompile Include="Source\BsProfilingManager.cpp" />
     <ClCompile Include="Source\BsProfilingManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsCoreRenderer.cpp" />
     <ClCompile Include="Source\BsCoreRenderer.cpp" />
+    <ClCompile Include="Source\BsSavedResourceData.cpp" />
     <ClCompile Include="Source\BsResourceListenerManager.cpp" />
     <ClCompile Include="Source\BsResourceListenerManager.cpp" />
     <ClCompile Include="Source\BsResourceManifest.cpp" />
     <ClCompile Include="Source\BsResourceManifest.cpp" />
     <ClCompile Include="Source\BsResourceMetaData.cpp" />
     <ClCompile Include="Source\BsResourceMetaData.cpp" />

+ 9 - 4
BansheeCore/BansheeCore.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
     <Filter Include="Header Files\Utility">
     <Filter Include="Header Files\Utility">
       <UniqueIdentifier>{2c09857e-4a4a-480f-8ebb-1661a9ce78dd}</UniqueIdentifier>
       <UniqueIdentifier>{2c09857e-4a4a-480f-8ebb-1661a9ce78dd}</UniqueIdentifier>
     </Filter>
     </Filter>
@@ -528,6 +524,12 @@
     <ClInclude Include="Include\BsUtility.h">
     <ClInclude Include="Include\BsUtility.h">
       <Filter>Header Files\Utility</Filter>
       <Filter>Header Files\Utility</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsSavedResourceData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSavedResourceDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -833,5 +835,8 @@
     <ClCompile Include="Source\BsUtility.cpp">
     <ClCompile Include="Source\BsUtility.cpp">
       <Filter>Source Files\Utility</Filter>
       <Filter>Source Files\Utility</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsSavedResourceData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 2 - 1
BansheeCore/Include/BsCorePrerequisites.h

@@ -318,7 +318,8 @@ namespace BansheeEngine
 		TID_TextureImportOptions = 1070,
 		TID_TextureImportOptions = 1070,
 		TID_ResourceMetaData = 1071,
 		TID_ResourceMetaData = 1071,
 		TID_GpuProgramInclude = 1072,
 		TID_GpuProgramInclude = 1072,
-		TID_Viewport = 1073
+		TID_Viewport = 1073,
+		TID_ResourceDependencies = 1074
 	};
 	};
 }
 }
 
 

+ 5 - 0
BansheeCore/Include/BsResource.h

@@ -30,6 +30,11 @@ namespace BansheeEngine
 		 */
 		 */
 		ResourceMetaDataPtr getMetaData() const { return mMetaData; }
 		ResourceMetaDataPtr getMetaData() const { return mMetaData; }
 
 
+		/**
+		 * @brief	Returns whether or not this resource is allowed to be asynchronously loaded.
+		 */
+		virtual bool allowAsyncLoading() const { return true; }
+
 	protected:
 	protected:
 		friend class Resources;
 		friend class Resources;
 
 

+ 42 - 0
BansheeCore/Include/BsSavedResourceData.h

@@ -0,0 +1,42 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Contains information about a resource saved to the disk.
+	 *
+	 * @note	Purpose of this class is primarily to be a wrapper around a list of objects
+	 *			to make serialization easier.
+	 */
+	class BS_CORE_EXPORT SavedResourceData : public IReflectable
+	{
+	public:
+		SavedResourceData();
+		SavedResourceData(const Vector<HResource>& dependencies, bool allowAsync);
+
+		/**
+		 * @brief	Returns a list of all resource dependencies.
+		 */
+		const Vector<HResource>& getDependencies() const { return mDependencies; }
+
+		/**
+		 * @brief	Returns true if this resource is allow to be asynchronously loaded.
+		 */
+		bool allowAsyncLoading() const { return mAllowAsync; }
+
+	private:
+		Vector<HResource> mDependencies;
+		bool mAllowAsync;
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+	public:
+		friend class SavedResourceDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+	};
+}

+ 66 - 0
BansheeCore/Include/BsSavedResourceDataRTTI.h

@@ -0,0 +1,66 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsSavedResourceData.h"
+
+namespace BansheeEngine
+{
+	class BS_CORE_EXPORT SavedResourceDataRTTI : public RTTIType <SavedResourceData, IReflectable, SavedResourceDataRTTI>
+	{
+	private:
+		HResource& getDependency(SavedResourceData* obj, UINT32 arrayIdx)
+		{
+			return obj->mDependencies[arrayIdx];
+		}
+
+		void setDependency(SavedResourceData* obj, UINT32 arrayIdx, HResource& val)
+		{
+			obj->mDependencies[arrayIdx] = val;
+		}
+
+		UINT32 getNumDependencies(SavedResourceData* obj)
+		{
+			return (UINT32)obj->mDependencies.size();
+		}
+
+		void setNumDependencies(SavedResourceData* obj, UINT32 numEntries)
+		{
+			obj->mDependencies = Vector<HResource>(numEntries);
+		}
+
+		bool& getAllowAsyncLoading(SavedResourceData* obj)
+		{
+			return obj->mAllowAsync;
+		}
+
+		void setAllowAsyncLoading(SavedResourceData* obj, bool& value)
+		{
+			obj->mAllowAsync = value;
+		}
+
+	public:
+		SavedResourceDataRTTI()
+		{
+			addReflectableArrayField("mDependencies", 0, &SavedResourceDataRTTI::getDependency, &SavedResourceDataRTTI::getNumDependencies,
+				&SavedResourceDataRTTI::setDependency, &SavedResourceDataRTTI::setNumDependencies);
+			addPlainField("mAllowAsync", 1, &SavedResourceDataRTTI::getAllowAsyncLoading, &SavedResourceDataRTTI::setAllowAsyncLoading);
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "Resource";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_ResourceDependencies;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			return bs_shared_ptr<SavedResourceData>();
+		}
+	};
+}

+ 4 - 4
BansheeCore/Source/BsResourceManifest.cpp

@@ -135,14 +135,14 @@ namespace BansheeEngine
 			copy->mUUIDToFilePath[elem.first] = elementRelativePath;
 			copy->mUUIDToFilePath[elem.first] = elementRelativePath;
 		}
 		}
 
 
-		FileSerializer fs;
-		fs.encode(copy.get(), path);
+		FileEncoder fs(path);
+		fs.encode(copy.get());
 	}
 	}
 
 
 	ResourceManifestPtr ResourceManifest::load(const Path& path, const Path& relativePath)
 	ResourceManifestPtr ResourceManifest::load(const Path& path, const Path& relativePath)
 	{
 	{
-		FileSerializer fs;
-		ResourceManifestPtr manifest = std::static_pointer_cast<ResourceManifest>(fs.decode(path));
+		FileDecoder fs(path);
+		ResourceManifestPtr manifest = std::static_pointer_cast<ResourceManifest>(fs.decode());
 
 
 		ResourceManifestPtr copy = create(manifest->mName);
 		ResourceManifestPtr copy = create(manifest->mName);
 
 

+ 16 - 4
BansheeCore/Source/BsResources.cpp

@@ -8,6 +8,8 @@
 #include "BsUUID.h"
 #include "BsUUID.h"
 #include "BsPath.h"
 #include "BsPath.h"
 #include "BsDebug.h"
 #include "BsDebug.h"
+#include "BsUtility.h"
+#include "BsSavedResourceData.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -105,6 +107,11 @@ namespace BansheeEngine
 		if(!foundUUID)
 		if(!foundUUID)
 			uuid = UUIDGenerator::instance().generateRandom();
 			uuid = UUIDGenerator::instance().generateRandom();
 
 
+		// Load saved resource data
+		{
+
+		}
+
 		{
 		{
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
 			auto iterFind = mLoadedResources.find(uuid);
 			auto iterFind = mLoadedResources.find(uuid);
@@ -171,8 +178,9 @@ namespace BansheeEngine
 
 
 	ResourcePtr Resources::loadFromDiskAndDeserialize(const Path& filePath)
 	ResourcePtr Resources::loadFromDiskAndDeserialize(const Path& filePath)
 	{
 	{
-		FileSerializer fs;
-		std::shared_ptr<IReflectable> loadedData = fs.decode(filePath);
+		FileDecoder fs(filePath);
+		fs.skip(); // Skipped over saved resource data
+		std::shared_ptr<IReflectable> loadedData = fs.decode();
 
 
 		if(loadedData == nullptr)
 		if(loadedData == nullptr)
 			BS_EXCEPT(InternalErrorException, "Unable to load resource.");
 			BS_EXCEPT(InternalErrorException, "Unable to load resource.");
@@ -237,8 +245,12 @@ namespace BansheeEngine
 
 
 		mDefaultResourceManifest->registerResource(resource.getUUID(), filePath);
 		mDefaultResourceManifest->registerResource(resource.getUUID(), filePath);
 
 
-		FileSerializer fs;
-		fs.encode(resource.get(), filePath);
+		Vector<HResource> dependencyList = Utility::findResourceDependencies(*resource.get(), false);
+		SPtr<SavedResourceData> resourceData = bs_shared_ptr<SavedResourceData>(dependencyList, resource->allowAsyncLoading());
+
+		FileEncoder fs(filePath);
+		fs.encode(resourceData.get());
+		fs.encode(resource.get());
 	}
 	}
 
 
 	void Resources::registerResourceManifest(const ResourceManifestPtr& manifest)
 	void Resources::registerResourceManifest(const ResourceManifestPtr& manifest)

+ 25 - 0
BansheeCore/Source/BsSavedResourceData.cpp

@@ -0,0 +1,25 @@
+#include "BsSavedResourceData.h"
+#include "BsSavedResourceDataRTTI.h"
+
+namespace BansheeEngine
+{
+	SavedResourceData::SavedResourceData()
+		:mAllowAsync(true)
+	{ }
+
+	SavedResourceData::SavedResourceData(const Vector<HResource>& dependencies, bool allowAsync)
+		:mDependencies(dependencies), mAllowAsync(allowAsync)
+	{
+
+	}
+
+	RTTITypeBase* SavedResourceData::getRTTIStatic()
+	{
+		return SavedResourceDataRTTI::instance();
+	}
+
+	RTTITypeBase* SavedResourceData::getRTTI() const
+	{
+		return SavedResourceData::getRTTIStatic();
+	}
+}

+ 4 - 4
BansheeEditor/Source/BsEditorApplication.cpp

@@ -422,8 +422,8 @@ namespace BansheeEngine
 
 
 		if(FileSystem::exists(layoutPath))
 		if(FileSystem::exists(layoutPath))
 		{
 		{
-			FileSerializer fs;
-			return std::static_pointer_cast<EditorWidgetLayout>(fs.decode(layoutPath));
+			FileDecoder fs(layoutPath);
+			return std::static_pointer_cast<EditorWidgetLayout>(fs.decode());
 		}
 		}
 
 
 		return nullptr;
 		return nullptr;
@@ -434,8 +434,8 @@ namespace BansheeEngine
 		Path layoutPath = getActiveProjectPath();
 		Path layoutPath = getActiveProjectPath();
 		layoutPath.append(WIDGET_LAYOUT_PATH);
 		layoutPath.append(WIDGET_LAYOUT_PATH);
 
 
-		FileSerializer fs;
-		fs.encode(layout.get(), layoutPath);
+		FileEncoder fs(layoutPath);
+		fs.encode(layout.get());
 	}
 	}
 
 
 	EditorApplication& gEditorApplication()
 	EditorApplication& gEditorApplication()

+ 10 - 10
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -351,10 +351,10 @@ namespace BansheeEngine
 
 
 		if(resource->meta == nullptr)
 		if(resource->meta == nullptr)
 		{
 		{
-			FileSerializer fs;
 			if(FileSystem::isFile(metaPath))
 			if(FileSystem::isFile(metaPath))
 			{
 			{
-				std::shared_ptr<IReflectable> loadedMeta = fs.decode(metaPath);
+				FileDecoder fs(metaPath);
+				std::shared_ptr<IReflectable> loadedMeta = fs.decode();
 
 
 				if(loadedMeta != nullptr && loadedMeta->isDerivedFrom(ProjectResourceMeta::getRTTIStatic()))
 				if(loadedMeta != nullptr && loadedMeta->isDerivedFrom(ProjectResourceMeta::getRTTIStatic()))
 				{
 				{
@@ -383,8 +383,8 @@ namespace BansheeEngine
 				UINT32 typeId = importedResource->getTypeId();
 				UINT32 typeId = importedResource->getTypeId();
 
 
 				resource->meta = ProjectResourceMeta::create(importedResource.getUUID(), typeId, subMeta, importOptions);
 				resource->meta = ProjectResourceMeta::create(importedResource.getUUID(), typeId, subMeta, importOptions);
-				FileSerializer fs;
-				fs.encode(resource->meta.get(), metaPath);
+				FileEncoder fs(metaPath);
+				fs.encode(resource->meta.get());
 			}
 			}
 			else
 			else
 			{
 			{
@@ -704,8 +704,8 @@ namespace BansheeEngine
 		libraryEntriesPath.append(INTERNAL_RESOURCES_DIR);
 		libraryEntriesPath.append(INTERNAL_RESOURCES_DIR);
 		libraryEntriesPath.append(LIBRARY_ENTRIES_FILENAME);
 		libraryEntriesPath.append(LIBRARY_ENTRIES_FILENAME);
 
 
-		FileSerializer fs;
-		fs.encode(libEntries.get(), libraryEntriesPath);
+		FileEncoder fs(libraryEntriesPath);
+		fs.encode(libEntries.get());
 
 
 		Path resourceManifestPath = mProjectFolder;
 		Path resourceManifestPath = mProjectFolder;
 		resourceManifestPath.append(INTERNAL_RESOURCES_DIR);
 		resourceManifestPath.append(INTERNAL_RESOURCES_DIR);
@@ -730,8 +730,8 @@ namespace BansheeEngine
 
 
 		if(FileSystem::exists(libraryEntriesPath))
 		if(FileSystem::exists(libraryEntriesPath))
 		{
 		{
-			FileSerializer fs;
-			std::shared_ptr<ProjectLibraryEntries> libEntries = std::static_pointer_cast<ProjectLibraryEntries>(fs.decode(libraryEntriesPath));
+			FileDecoder fs(libraryEntriesPath);
+			std::shared_ptr<ProjectLibraryEntries> libEntries = std::static_pointer_cast<ProjectLibraryEntries>(fs.decode());
 
 
 			*mRootEntry = libEntries->getRootEntry();
 			*mRootEntry = libEntries->getRootEntry();
 			for(auto& child : mRootEntry->mChildren)
 			for(auto& child : mRootEntry->mChildren)
@@ -760,10 +760,10 @@ namespace BansheeEngine
 						Path metaPath = resEntry->path;
 						Path metaPath = resEntry->path;
 						metaPath.setFilename(metaPath.getWFilename() + L".meta");
 						metaPath.setFilename(metaPath.getWFilename() + L".meta");
 
 
-						FileSerializer fs;
 						if(FileSystem::isFile(metaPath))
 						if(FileSystem::isFile(metaPath))
 						{
 						{
-							std::shared_ptr<IReflectable> loadedMeta = fs.decode(metaPath);
+							FileDecoder fs(metaPath);
+							std::shared_ptr<IReflectable> loadedMeta = fs.decode();
 
 
 							if(loadedMeta != nullptr && loadedMeta->isDerivedFrom(ProjectResourceMeta::getRTTIStatic()))
 							if(loadedMeta != nullptr && loadedMeta->isDerivedFrom(ProjectResourceMeta::getRTTIStatic()))
 							{
 							{

+ 2 - 2
BansheeEditor/Source/BsResourceImporter.cpp

@@ -33,8 +33,8 @@ namespace BansheeEngine
 
 
 	ResourcePtr ResourceImporter::import(const Path& filePath, ConstImportOptionsPtr importOptions)
 	ResourcePtr ResourceImporter::import(const Path& filePath, ConstImportOptionsPtr importOptions)
 	{
 	{
-		FileSerializer fs;
-		std::shared_ptr<IReflectable> loadedData = fs.decode(filePath);
+		FileDecoder fs(filePath);
+		std::shared_ptr<IReflectable> loadedData = fs.decode();
 
 
 		if (loadedData == nullptr)
 		if (loadedData == nullptr)
 			BS_EXCEPT(InternalErrorException, "Unable to import resource.");
 			BS_EXCEPT(InternalErrorException, "Unable to import resource.");

+ 0 - 4
BansheeEditorExec/BansheeEditorExec.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="BsEditorExec.cpp">
     <ClCompile Include="BsEditorExec.cpp">

+ 0 - 4
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
     <Filter Include="Header Files\GUI">
     <Filter Include="Header Files\GUI">
       <UniqueIdentifier>{d21e5e3c-e647-46a5-99e6-e2fdeb3dc842}</UniqueIdentifier>
       <UniqueIdentifier>{d21e5e3c-e647-46a5-99e6-e2fdeb3dc842}</UniqueIdentifier>
     </Filter>
     </Filter>

+ 0 - 4
BansheeUtility/BansheeUtility.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
     <Filter Include="Header Files\Prerequisites">
     <Filter Include="Header Files\Prerequisites">
       <UniqueIdentifier>{1a68be3e-3394-4b01-9532-2fe9db03afe0}</UniqueIdentifier>
       <UniqueIdentifier>{1a68be3e-3394-4b01-9532-2fe9db03afe0}</UniqueIdentifier>
     </Filter>
     </Filter>

+ 30 - 17
BansheeUtility/Include/BsFileSerializer.h

@@ -8,41 +8,54 @@ namespace BansheeEngine
 	// a generic Serializer interface so it may write both binary, plain-text or some other form of data.
 	// a generic Serializer interface so it may write both binary, plain-text or some other form of data.
 
 
 	/**
 	/**
-	  * @brief	Encodes/decodes an IReflectable object from/to a file. 
-	  */
-	class BS_UTILITY_EXPORT FileSerializer
+	 * @brief	Encodes the provided object to the specified file using the RTTI system.
+	 */
+	class BS_UTILITY_EXPORT FileEncoder
 	{
 	{
 	public:
 	public:
-		FileSerializer();
-		~FileSerializer();
+		FileEncoder(const Path& fileLocation);
+		~FileEncoder();
 
 
 		/**
 		/**
 		 * @brief	Parses the provided object, serializes all of its data as specified by its
 		 * @brief	Parses the provided object, serializes all of its data as specified by its
 		 *			RTTIType and saves the serialized data to the provided file location.
 		 *			RTTIType and saves the serialized data to the provided file location.
 		 */
 		 */
-		void encode(IReflectable* object, const Path& fileLocation);
+		void encode(IReflectable* object);
 
 
+	private:
 		/**
 		/**
-		 * @brief	Deserializes an IReflectable object by reading the binary data at
-		 *			the provided file location.
+		 * @brief	Called by the binary serializer whenever the buffer gets full.
 		 */
 		 */
-		std::shared_ptr<IReflectable> decode(const Path& fileLocation);
+		UINT8* flushBuffer(UINT8* bufferStart, int bytesWritten, UINT32& newBufferSize);
 
 
-	private:
 		std::ofstream mOutputStream;
 		std::ofstream mOutputStream;
 		UINT8* mWriteBuffer;
 		UINT8* mWriteBuffer;
 
 
-		std::ifstream mInputStream;
+		static const UINT32 WRITE_BUFFER_SIZE = 2048;
+	};
+
+	/**
+	 * @brief	Decodes objects from the specified file using the RTTI system.
+	 */
+	class BS_UTILITY_EXPORT FileDecoder
+	{
+	public:
+		FileDecoder(const Path& fileLocation);
+		~FileDecoder();
 
 
 		/**
 		/**
-		 * @brief	Called by the binary serializer whenever the buffer gets full.
+		 * @brief	Deserializes an IReflectable object by reading the binary data at
+		 *			the provided file location.
 		 */
 		 */
-		UINT8* flushBuffer(UINT8* bufferStart, int bytesWritten, UINT32& newBufferSize);
+		std::shared_ptr<IReflectable> decode();
+
+		/**
+		 * @brief	Skips over than object in the file. Calling "decode" will decode
+		 *			the next object.
+		 */
+		void skip();
 
 
-		/************************************************************************/
-		/* 								CONSTANTS	                     		*/
-		/************************************************************************/
 	private:
 	private:
-		static const UINT32 WRITE_BUFFER_SIZE = 2048;
+		std::ifstream mInputStream;
 	};
 	};
 }
 }

+ 55 - 24
BansheeUtility/Source/BsFileSerializer.cpp

@@ -12,63 +12,94 @@ using namespace std::placeholders;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	FileSerializer::FileSerializer()
+	FileEncoder::FileEncoder(const Path& fileLocation)
+		:mWriteBuffer(nullptr)
 	{
 	{
 		mWriteBuffer = (UINT8*)bs_alloc<ScratchAlloc>(WRITE_BUFFER_SIZE);
 		mWriteBuffer = (UINT8*)bs_alloc<ScratchAlloc>(WRITE_BUFFER_SIZE);
+
+		Path parentDir = fileLocation.getDirectory();
+		if (!FileSystem::exists(parentDir))
+			FileSystem::createDir(parentDir);
+
+		mOutputStream.open(fileLocation.toString().c_str(), std::ios::out | std::ios::binary);
 	}
 	}
 
 
-	FileSerializer::~FileSerializer()
+	FileEncoder::~FileEncoder()
 	{
 	{
 		bs_free<ScratchAlloc>(mWriteBuffer);
 		bs_free<ScratchAlloc>(mWriteBuffer);
+
+		mOutputStream.close();
+		mOutputStream.clear();
 	}
 	}
 
 
-	void FileSerializer::encode(IReflectable* object, const Path& fileLocation)
+	void FileEncoder::encode(IReflectable* object)
 	{
 	{
-		Path parentDir = fileLocation.getDirectory();
-		if (!FileSystem::exists(parentDir))
-			FileSystem::createDir(parentDir);
-
-		mOutputStream.open(fileLocation.toString().c_str(), std::ios::out | std::ios::binary);
+		UINT64 curPos = (UINT64)mOutputStream.tellp();
+		mOutputStream.seekp(sizeof(UINT32), std::ios_base::cur);
 
 
 		BinarySerializer bs;
 		BinarySerializer bs;
 		int totalBytesWritten = 0;
 		int totalBytesWritten = 0;
-		bs.encode(object, mWriteBuffer, WRITE_BUFFER_SIZE, &totalBytesWritten, std::bind(&FileSerializer::flushBuffer, this, _1, _2, _3));
+		bs.encode(object, mWriteBuffer, WRITE_BUFFER_SIZE, &totalBytesWritten, std::bind(&FileEncoder::flushBuffer, this, _1, _2, _3));
 
 
-		mOutputStream.close();
-		mOutputStream.clear();
+		mOutputStream.seekp(curPos);
+		mOutputStream.write((char*)&totalBytesWritten, sizeof(totalBytesWritten));
+		mOutputStream.seekp(totalBytesWritten, std::ios_base::cur);
+	}
+
+	UINT8* FileEncoder::flushBuffer(UINT8* bufferStart, int bytesWritten, UINT32& newBufferSize)
+	{
+		mOutputStream.write((const char*)bufferStart, bytesWritten);
+
+		return bufferStart;
 	}
 	}
 
 
-	std::shared_ptr<IReflectable> FileSerializer::decode(const Path& fileLocation)
+	FileDecoder::FileDecoder(const Path& fileLocation)
 	{
 	{
 		mInputStream.open(fileLocation.toString().c_str(), std::ios::in | std::ios::ate | std::ios::binary);
 		mInputStream.open(fileLocation.toString().c_str(), std::ios::in | std::ios::ate | std::ios::binary);
-		
+
 		std::streamoff fileSize = mInputStream.tellg();
 		std::streamoff fileSize = mInputStream.tellg();
-		if(fileSize > std::numeric_limits<UINT32>::max())
+		if (fileSize > std::numeric_limits<UINT32>::max())
 		{
 		{
-			BS_EXCEPT(InternalErrorException, 
+			BS_EXCEPT(InternalErrorException,
 				"File size is larger that UINT32 can hold. Ask a programmer to use a bigger data type.");
 				"File size is larger that UINT32 can hold. Ask a programmer to use a bigger data type.");
 		}
 		}
 
 
-		UINT8* readBuffer = (UINT8*)bs_alloc<ScratchAlloc>((UINT32)fileSize); // TODO - Low priority. Consider upgrading BinarySerializer so we don't have to read everything at once
-
 		mInputStream.seekg(0, std::ios::beg);
 		mInputStream.seekg(0, std::ios::beg);
-		mInputStream.read((char*)readBuffer, fileSize);
-
-		BinarySerializer bs;
-		std::shared_ptr<IReflectable> object = bs.decode(readBuffer, (UINT32)fileSize);
+	}
 
 
+	FileDecoder::~FileDecoder()
+	{
 		mInputStream.close();
 		mInputStream.close();
 		mInputStream.clear();
 		mInputStream.clear();
+	}
+
+	std::shared_ptr<IReflectable> FileDecoder::decode()
+	{
+		if (mInputStream.eof())
+			return nullptr;
+
+		UINT32 objectSize = 0;
+		mInputStream.read((char*)&objectSize, sizeof(objectSize));
+
+		UINT8* readBuffer = (UINT8*)bs_alloc<ScratchAlloc>((UINT32)objectSize); // TODO - Low priority. Consider upgrading BinarySerializer so we don't have to read everything at once
+		mInputStream.read((char*)readBuffer, objectSize);
+
+		BinarySerializer bs;
+		std::shared_ptr<IReflectable> object = bs.decode(readBuffer, objectSize);
 
 
 		bs_free<ScratchAlloc>(readBuffer);
 		bs_free<ScratchAlloc>(readBuffer);
 
 
 		return object;
 		return object;
 	}
 	}
 
 
-	UINT8* FileSerializer::flushBuffer(UINT8* bufferStart, int bytesWritten, UINT32& newBufferSize)
+	void FileDecoder::skip()
 	{
 	{
-		mOutputStream.write((const char*)bufferStart, bytesWritten);
+		if (mInputStream.eof())
+			return;
 
 
-		return bufferStart;
+		UINT32 objectSize = 0;
+		mInputStream.read((char*)&objectSize, sizeof(objectSize));
+
+		mInputStream.seekg(objectSize, std::ios::cur);
 	}
 	}
 }
 }

+ 0 - 4
ExampleProject/ExampleProject.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
       <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Main\Main.cpp">
     <ClCompile Include="Main\Main.cpp">

+ 7 - 2
TODO.txt

@@ -5,11 +5,16 @@ See GDrive/Resources doc for resources refactor
 There seems to be some kind of memory corruption that happens when cloning game objects. During one clone the field entries provided to
 There seems to be some kind of memory corruption that happens when cloning game objects. During one clone the field entries provided to
 ManagedSerializeArray::deserializeManagedInstance were reported as ManagedSerializedArray instead of ManagerSerializedFieldData types.
 ManagedSerializeArray::deserializeManagedInstance were reported as ManagedSerializedArray instead of ManagerSerializedFieldData types.
 It's inconsistent to reproduce but started happening after I have modified managed object serialization to be on-demand. It's possibly
 It's inconsistent to reproduce but started happening after I have modified managed object serialization to be on-demand. It's possibly
-related to lambdas not capturing types as I expect them to.
+related to lambdas not capturing types as I expect them to. It always happens in the same place.
 
 
-TODO - Material waits to Shader to be loaded but doesn't wait for shader GpuPrograms. 
+TODO - Material waits to Shader to be loaded but doesn't wait for shader GpuPrograms or state objects.
  - What's the best way to ensure initialization is done when all these are loaded?
  - What's the best way to ensure initialization is done when all these are loaded?
 
 
+ Modify Resources so it loads resource dependencies and that actual resource gets loaded from the proper offset in file
+Test if stuff compiles and runs - commit
+Remove loading code from ResourceHandle
+Add loading code to Resources
+
 When resource loading starts synchonously read all dependencies (and recurse over their dependencies too)
 When resource loading starts synchonously read all dependencies (and recurse over their dependencies too)
  - Create a ResourceLoadGroup that contains all the non-loaded resources
  - Create a ResourceLoadGroup that contains all the non-loaded resources
  - Cue async loads for all resources
  - Cue async loads for all resources