Преглед изворни кода

Advanced resource loading WIP stage 1

Marko Pintera пре 11 година
родитељ
комит
eb4de059fc

+ 3 - 0
BansheeCore/BansheeCore.vcxproj

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

+ 9 - 4
BansheeCore/BansheeCore.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </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">
       <UniqueIdentifier>{2c09857e-4a4a-480f-8ebb-1661a9ce78dd}</UniqueIdentifier>
     </Filter>
@@ -528,6 +524,12 @@
     <ClInclude Include="Include\BsUtility.h">
       <Filter>Header Files\Utility</Filter>
     </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>
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -833,5 +835,8 @@
     <ClCompile Include="Source\BsUtility.cpp">
       <Filter>Source Files\Utility</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsSavedResourceData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 1
BansheeCore/Include/BsCorePrerequisites.h

@@ -318,7 +318,8 @@ namespace BansheeEngine
 		TID_TextureImportOptions = 1070,
 		TID_ResourceMetaData = 1071,
 		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; }
 
+		/**
+		 * @brief	Returns whether or not this resource is allowed to be asynchronously loaded.
+		 */
+		virtual bool allowAsyncLoading() const { return true; }
+
 	protected:
 		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;
 		}
 
-		FileSerializer fs;
-		fs.encode(copy.get(), path);
+		FileEncoder fs(path);
+		fs.encode(copy.get());
 	}
 
 	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);
 

+ 16 - 4
BansheeCore/Source/BsResources.cpp

@@ -8,6 +8,8 @@
 #include "BsUUID.h"
 #include "BsPath.h"
 #include "BsDebug.h"
+#include "BsUtility.h"
+#include "BsSavedResourceData.h"
 
 namespace BansheeEngine
 {
@@ -105,6 +107,11 @@ namespace BansheeEngine
 		if(!foundUUID)
 			uuid = UUIDGenerator::instance().generateRandom();
 
+		// Load saved resource data
+		{
+
+		}
+
 		{
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
 			auto iterFind = mLoadedResources.find(uuid);
@@ -171,8 +178,9 @@ namespace BansheeEngine
 
 	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)
 			BS_EXCEPT(InternalErrorException, "Unable to load resource.");
@@ -237,8 +245,12 @@ namespace BansheeEngine
 
 		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)

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

+ 10 - 10
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -351,10 +351,10 @@ namespace BansheeEngine
 
 		if(resource->meta == nullptr)
 		{
-			FileSerializer fs;
 			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()))
 				{
@@ -383,8 +383,8 @@ namespace BansheeEngine
 				UINT32 typeId = importedResource->getTypeId();
 
 				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
 			{
@@ -704,8 +704,8 @@ namespace BansheeEngine
 		libraryEntriesPath.append(INTERNAL_RESOURCES_DIR);
 		libraryEntriesPath.append(LIBRARY_ENTRIES_FILENAME);
 
-		FileSerializer fs;
-		fs.encode(libEntries.get(), libraryEntriesPath);
+		FileEncoder fs(libraryEntriesPath);
+		fs.encode(libEntries.get());
 
 		Path resourceManifestPath = mProjectFolder;
 		resourceManifestPath.append(INTERNAL_RESOURCES_DIR);
@@ -730,8 +730,8 @@ namespace BansheeEngine
 
 		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();
 			for(auto& child : mRootEntry->mChildren)
@@ -760,10 +760,10 @@ namespace BansheeEngine
 						Path metaPath = resEntry->path;
 						metaPath.setFilename(metaPath.getWFilename() + L".meta");
 
-						FileSerializer fs;
 						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()))
 							{

+ 2 - 2
BansheeEditor/Source/BsResourceImporter.cpp

@@ -33,8 +33,8 @@ namespace BansheeEngine
 
 	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)
 			BS_EXCEPT(InternalErrorException, "Unable to import resource.");

+ 0 - 4
BansheeEditorExec/BansheeEditorExec.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </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>
     <ClCompile Include="BsEditorExec.cpp">

+ 0 - 4
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </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">
       <UniqueIdentifier>{d21e5e3c-e647-46a5-99e6-e2fdeb3dc842}</UniqueIdentifier>
     </Filter>

+ 0 - 4
BansheeUtility/BansheeUtility.vcxproj.filters

@@ -9,10 +9,6 @@
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </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">
       <UniqueIdentifier>{1a68be3e-3394-4b01-9532-2fe9db03afe0}</UniqueIdentifier>
     </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.
 
 	/**
-	  * @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:
-		FileSerializer();
-		~FileSerializer();
+		FileEncoder(const Path& fileLocation);
+		~FileEncoder();
 
 		/**
 		 * @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.
 		 */
-		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;
 		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:
-		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
 {
-	FileSerializer::FileSerializer()
+	FileEncoder::FileEncoder(const Path& fileLocation)
+		:mWriteBuffer(nullptr)
 	{
 		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);
+
+		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;
 		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);
-		
+
 		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.");
 		}
 
-		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.read((char*)readBuffer, fileSize);
-
-		BinarySerializer bs;
-		std::shared_ptr<IReflectable> object = bs.decode(readBuffer, (UINT32)fileSize);
+	}
 
+	FileDecoder::~FileDecoder()
+	{
 		mInputStream.close();
 		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);
 
 		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>
       <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </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>
     <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
 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
-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?
 
+ 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)
  - Create a ResourceLoadGroup that contains all the non-loaded resources
  - Cue async loads for all resources