Beispiel #1
0
/// Update during the package preload process.
void LoosePackageLoader::TickPreload()
{
	HELIUM_ASSERT( m_startPreloadCounter != 0 );
	HELIUM_ASSERT( m_preloadedCounter == 0 );

	AsyncLoader& rAsyncLoader = AsyncLoader::GetStaticInstance();

	bool bAllFileRequestsDone = true;

	// Walk through every load request
	for (size_t i = 0; i < m_fileReadRequests.GetSize();)
	{
		FileReadRequest &rRequest = m_fileReadRequests[i];
		HELIUM_ASSERT(rRequest.asyncLoadId);
		HELIUM_ASSERT(rRequest.pLoadBuffer);

		size_t bytes_read = 0;
		if (!rAsyncLoader.TrySyncRequest(rRequest.asyncLoadId, bytes_read))
		{
			// Havn't finished reading yet, move on to next entry
			bAllFileRequestsDone = false;
			++i;
			continue;
		}

		HELIUM_ASSERT(bytes_read == rRequest.expectedSize);
		if( IsInvalid( bytes_read ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader: Failed to read the contents of async load request \"%d\".\n" ),
				rRequest.asyncLoadId );
		}
		else if( bytes_read != rRequest.expectedSize)
		{
			HELIUM_TRACE(
				TraceLevels::Warning,
				( TXT( "LoosePackageLoader: Attempted to read %" ) PRIuSZ TXT( " bytes from package file \"%s\", " )
				TXT( "but only %" ) PRIuSZ TXT( " bytes were read.\n" ) ),
				rRequest.expectedSize,
				bytes_read );
		}
		else
		{
			HELIUM_ASSERT( rRequest.expectedSize < ~static_cast<size_t>( 0 ) );

			// the name is deduced from the file name (bad idea to store it in the file)
			Name name ( m_fileReadRequests[i].filePath.Basename().c_str() );

			// read some preliminary data from the json
			struct PreliminaryObjectHandler : rapidjson::BaseReaderHandler<>
			{
				Helium::Name typeName;
				Helium::String templatePath;
				bool templateIsNext;

				PreliminaryObjectHandler()
					: typeName( ENullName () )
					, templatePath( "" )
				{
					templateIsNext = false;
				}

				void String(const Ch* chars, rapidjson::SizeType length, bool copy)
				{
					if ( typeName.IsEmpty() )
					{
						typeName.Set( Helium::String ( chars, length ) );
						return;
					}

					if ( templatePath.IsEmpty() )
					{
						Helium::String str ( chars, length ); 

						if ( templateIsNext )
						{
							templatePath = str;
							templateIsNext = false;
							return;
						}
						else
						{
							if ( str == "m_spTemplate" )
							{
								templateIsNext = true;
								return;
							}
						}
					}
				}

				void StartObject() { Default(); }
				void EndObject( rapidjson::SizeType ) { Default(); }

			} handler;

			// non destructive in-place stream helper
			rapidjson::StringStream stream ( static_cast< char* >( rRequest.pLoadBuffer ) );

			// the main reader object
			rapidjson::Reader reader;
			if ( reader.Parse< rapidjson::kParseDefaultFlags >( stream, handler ) )
			{
				SerializedObjectData* pObjectData = m_objects.New();
				HELIUM_ASSERT( pObjectData );
				HELIUM_VERIFY( pObjectData->objectPath.Set( name, false, m_packagePath ) );
				pObjectData->templatePath.Set( handler.templatePath );
				pObjectData->typeName = handler.typeName;
				pObjectData->filePath = rRequest.filePath;
				pObjectData->fileTimeStamp = rRequest.fileTimestamp;
				pObjectData->bMetadataGood = true;

				HELIUM_TRACE(
					TraceLevels::Debug,
					TXT( "LoosePackageLoader: Success reading preliminary data for object '%s' from file '%s'.\n" ),
					*name,
					rRequest.filePath.c_str() );
			}
			else
			{
				HELIUM_TRACE(
					TraceLevels::Error,
					TXT( "LoosePackageLoader: Failure reading preliminary data for object '%s' from file '%s': %s\n" ),
					*name,
					rRequest.filePath.c_str(),
					reader.GetParseError() );
			}
		}

		// We're finished with this load, so deallocate memory and get rid of the request
		DefaultAllocator().Free( rRequest.pLoadBuffer );
		rRequest.pLoadBuffer = NULL;
		SetInvalid(rRequest.asyncLoadId);
		m_fileReadRequests.RemoveSwap(i);
	}

	// Wait for the parent package to finish loading.
	AssetPtr spParentPackage;
	if( IsValid( m_parentPackageLoadId ) )
	{
		AssetLoader* pAssetLoader = AssetLoader::GetStaticInstance();
		HELIUM_ASSERT( pAssetLoader );
		if( !pAssetLoader->TryFinishLoad( m_parentPackageLoadId, spParentPackage ) )
		{
			return;
		}

		SetInvalid( m_parentPackageLoadId );

		// Package loading should not fail.  If it does, this is a sign of a potentially serious issue.
		HELIUM_ASSERT( spParentPackage );
	}

	// Everything beyond this point "finalizes" the package preload, so stop here if we aren't ready to go
	if (!bAllFileRequestsDone)
	{
		return;
	}

	// Create the package object if it does not yet exist.
	Package* pPackage = m_spPackage;
	if( !pPackage )
	{
		HELIUM_ASSERT( spParentPackage ? !m_packagePath.GetParent().IsEmpty() : m_packagePath.GetParent().IsEmpty() );
		HELIUM_VERIFY( Asset::Create< Package >( m_spPackage, m_packagePath.GetName(), spParentPackage ) );
		pPackage = m_spPackage;
		HELIUM_ASSERT( pPackage );
		pPackage->SetLoader( this );
	}

	HELIUM_ASSERT( pPackage->GetLoader() == this );

	FilePath packageDirectoryPath;

	if ( !FileLocations::GetDataDirectory( packageDirectoryPath ) )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "LoosePackageLoader::TickPreload(): Could not get data directory.\n" ) );
		return;
	}

	packageDirectoryPath += m_packagePath.ToFilePathString().GetData();
	packageDirectoryPath += TXT("/");

	DirectoryIterator packageDirectory( packageDirectoryPath );
	for( ; !packageDirectory.IsDone(); packageDirectory.Next() )
	{
		const DirectoryIteratorItem& item = packageDirectory.GetItem();

		if ( !item.m_Path.IsFile() )
		{
			continue;
		}

		Name objectName( item.m_Path.Filename().c_str() );
		String objectNameString( item.m_Path.Filename().c_str() );

		size_t objectIndex = FindObjectByName( objectName );

		if( objectIndex != Invalid< size_t >() )
		{
			m_objects[ objectIndex ].fileTimeStamp = Helium::Max( 
				m_objects[ objectIndex ].fileTimeStamp, 
				static_cast< int64_t >( packageDirectory.GetItem().m_ModTime ) );

			continue;
		}

		// Check the extension to see if the file is supported by one of the resource handlers.
		ResourceHandler* pBestHandler = ResourceHandler::GetBestResourceHandlerForFile( objectNameString );

		if( pBestHandler )
		{
			// File extension matches a supported source asset type, so add it to the object list.
			const AssetType* pResourceType = pBestHandler->GetResourceType();
			HELIUM_ASSERT( pResourceType );

			HELIUM_TRACE(
				TraceLevels::Debug,
				( TXT( "LoosePackageLoader: Registered source asset file \"%s\" as as instance of resource " )
				TXT( "type \"%s\" in package \"%s\".\n" ) ),
				*objectNameString,
				*pResourceType->GetName(),
				*m_packagePath.ToString() );

			SerializedObjectData* pObjectData = m_objects.New();
			HELIUM_ASSERT( pObjectData );
			HELIUM_VERIFY( pObjectData->objectPath.Set( objectName, false, m_packagePath ) );
			pObjectData->typeName = pResourceType->GetName();
			pObjectData->templatePath.Clear();
			pObjectData->filePath.Clear();
			pObjectData->fileTimeStamp = packageDirectory.GetItem().m_ModTime;
			pObjectData->bMetadataGood = true;
		}
		else
		{
			HELIUM_TRACE(
				TraceLevels::Debug,
				( TXT( "LoosePackageLoader: Did not recognize \"%s\" as as instance of resource " )
				TXT( "in package \"%s\".\n" ) ),
				*objectNameString,
				*m_packagePath.ToString() );
			
			for ( AssetType::ConstIterator iter = AssetType::GetTypeBegin();
				iter != AssetType::GetTypeEnd(); ++iter)
			{
				HELIUM_TRACE(
					TraceLevels::Info,
					TXT( " - %s\n" ),
					*iter->GetName() );
			}
		}
	}

	// Package preloading is now complete.
	pPackage->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );
	pPackage->ConditionalFinalizeLoad();

	AtomicExchangeRelease( m_preloadedCounter, 1 );

	LooseAssetLoader::OnPackagePreloaded( this );
}
Beispiel #2
0
/// Update processing of object property preloading for a given load request.
///
/// @param[in] pRequest  Load request to process.
///
/// @return  True if object property preloading for the given load request has completed, false if not.
bool LoosePackageLoader::TickDeserialize( LoadRequest* pRequest )
{
	HELIUM_ASSERT( pRequest );
	HELIUM_ASSERT( !( pRequest->flags & LOAD_FLAG_PROPERTY_PRELOADED ) );

	Asset* pObject = pRequest->spObject;

	HELIUM_ASSERT( pRequest->index < m_objects.GetSize() );
	SerializedObjectData& rObjectData = m_objects[ pRequest->index ];

	// Wait for the template and owner objects to load.
	AssetLoader* pAssetLoader = AssetLoader::GetStaticInstance();
	HELIUM_ASSERT( pAssetLoader );

	if( !rObjectData.templatePath.IsEmpty() )
	{
		if( IsValid( pRequest->templateLoadId ) )
		{
			if( !pAssetLoader->TryFinishLoad( pRequest->templateLoadId, pRequest->spTemplate ) )
			{
				return false;
			}

			SetInvalid( pRequest->templateLoadId );
		}

		if( !pRequest->spTemplate )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader: Failed to load template object for \"%s\".\n" ),
				*rObjectData.objectPath.ToString() );

			if( pObject )
			{
				pObject->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );
				pObject->ConditionalFinalizeLoad();
			}

			pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

			return true;
		}
	}

	HELIUM_ASSERT( IsInvalid( pRequest->templateLoadId ) );
	Asset* pTemplate = pRequest->spTemplate;

	AssetPath ownerPath = rObjectData.objectPath.GetParent();
	if( !ownerPath.IsEmpty() )
	{
		if( IsValid( pRequest->ownerLoadId ) )
		{
			if( !pAssetLoader->TryFinishLoad( pRequest->ownerLoadId, pRequest->spOwner ) )
			{
				return false;
			}

			SetInvalid( pRequest->ownerLoadId );
		}

		if( !pRequest->spOwner )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader: Failed to load owner object for \"%s\".\n" ),
				*rObjectData.objectPath.ToString() );

			if( pObject )
			{
				pObject->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );
				pObject->ConditionalFinalizeLoad();
			}

			pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

			return true;
		}
	}

	HELIUM_ASSERT( IsInvalid( pRequest->ownerLoadId ) );
	Asset* pOwner = pRequest->spOwner;

	AssetType* pType = pRequest->spType;
	HELIUM_ASSERT( pType );

	HELIUM_ASSERT( !pOwner || pOwner->IsFullyLoaded() );
	HELIUM_ASSERT( !pTemplate || pTemplate->IsFullyLoaded() );

	AsyncLoader& rAsyncLoader = AsyncLoader::GetStaticInstance();
	FilePath object_file_path = m_packageDirPath + *rObjectData.objectPath.GetName() + TXT( "." ) + Persist::ArchiveExtensions[ Persist::ArchiveTypes::Json ];

	bool load_properties_from_file = true;
	size_t object_file_size = 0;
	if ( !IsValid( pRequest->asyncFileLoadId ) )
	{
		if (!object_file_path.IsFile())
		{
			if (pType->GetMetaClass()->IsType( Reflect::GetMetaClass< Resource >() ))
			{
				HELIUM_TRACE(
					TraceLevels::Info,
					TXT( "LoosePackageLoader::TickDeserialize(): No object file found for resource \"%s\". Expected file location: \"%s\". This is normal for newly added resources.\n" ),
					*rObjectData.objectPath.ToString(),
					*object_file_path);

				// We will allow continuing to load using all default properties. This behavior is to support dropping resources into the 
				// data property and autogenerating objects from them.
				load_properties_from_file = false;
			}
			else
			{
				HELIUM_TRACE(
					TraceLevels::Warning,
					TXT( "LoosePackageLoader::TickDeserialize(): No object file found for object \"%s\". Expected file location: \"%s\"\n" ),
					*rObjectData.objectPath.ToString(),
					*object_file_path);
			}
		}
		else
		{
			Status status;
			status.Read( object_file_path.Get().c_str() );
			int64_t i64_object_file_size = status.m_Size;

			if( i64_object_file_size == -1 )
			{
				HELIUM_TRACE(
					TraceLevels::Warning,
					TXT( "LoosePackageLoader::TickDeserialize(): Could not get file size for object file of object \"%s\". Expected file location: \"%s\"\n" ),
					*rObjectData.objectPath.ToString(),
					*object_file_path );
			}
			else if( i64_object_file_size == 0 )
			{
				HELIUM_TRACE(
					TraceLevels::Warning,
					TXT( "LoosePackageLoader::TickDeserialize(): Object file \"%s\" for objct \"%s\" is empty.\n" ),
					*object_file_path,
					*rObjectData.objectPath.ToString() );
			}
			else if( static_cast< uint64_t >( i64_object_file_size ) > static_cast< uint64_t >( ~static_cast< size_t >( 0 ) ) )
			{
				HELIUM_TRACE(
					TraceLevels::Error,
					( TXT( "LoosePackageLoader::TickDeserialize(): Object file \"%s\" exceeds the maximum size supported by " )
					TXT( "the current platform (file size: %" ) PRIu64 TXT( " bytes; max supported: %" ) PRIuSZ
					TXT( " bytes).\n" ) ),
					object_file_path.c_str(),
					static_cast< uint64_t >( i64_object_file_size ),
					~static_cast< size_t >( 0 ) );
			}
			else
			{
				object_file_size = static_cast< size_t >(i64_object_file_size);
			}
		}
		
		if (!load_properties_from_file)
		{
			HELIUM_ASSERT(!object_file_size);
		}
		else if (!object_file_size)
		{
			pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;
			return true;
		}
		else
		{
			HELIUM_ASSERT( !pRequest->pAsyncFileLoadBuffer );
			pRequest->pAsyncFileLoadBuffer = DefaultAllocator().Allocate( object_file_size );
			HELIUM_ASSERT( pRequest->pAsyncFileLoadBuffer );

			pRequest->asyncFileLoadBufferSize = object_file_size;

			pRequest->asyncFileLoadId = rAsyncLoader.QueueRequest(
				pRequest->pAsyncFileLoadBuffer,
				String(object_file_path.c_str()),
				0,
				pRequest->asyncFileLoadBufferSize);
		}
		
	}
	
	size_t bytesRead = 0;
	if (load_properties_from_file)
	{
		HELIUM_ASSERT( IsValid( pRequest->asyncFileLoadId ) );

		if ( !rAsyncLoader.TrySyncRequest( pRequest->asyncFileLoadId, bytesRead ) )
		{
			return false;
		}
	}

	/////// POINT OF NO RETURN: We *will* return true after this point, and the object *will* be finished preloading,
	/////// for good or for bad.

	SetInvalid(pRequest->asyncFileLoadId);
	bool object_creation_failure = false;

	// If we already had an existing object, make sure the type and template match.
	if( pObject )
	{
		const AssetType* pExistingType = pObject->GetAssetType();
		HELIUM_ASSERT( pExistingType );
		if( pExistingType != pType )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				( TXT( "LoosePackageLoader: Cannot load \"%s\" using the existing object as the types do not match " )
				TXT( "(existing type: \"%s\"; serialized type: \"%s\".\n" ) ),
				*rObjectData.objectPath.ToString(),
				*pExistingType->GetName(),
				*pType->GetName() );

			pObject->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );
			pObject->ConditionalFinalizeLoad();
				
			object_creation_failure = true;
		}
	}
	else
	{
		bool bCreateResult = false;
		if (pRequest->forceReload)
		{
			// Create the object.
			bCreateResult = Asset::CreateObject(
				pRequest->spObject,
				pType,
				Name( NULL_NAME ),
				NULL,
				pTemplate );
		}
		else
		{
			// Create the object.
			bCreateResult = Asset::CreateObject(
				pRequest->spObject,
				pType,
				rObjectData.objectPath.GetName(),
				pOwner,
				pTemplate );
		}

		if( !bCreateResult )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader: Failed to create \"%s\" during loading.\n" ),
				*rObjectData.objectPath.ToString() );
				
			object_creation_failure = true;
		}

		pObject = pRequest->spObject;
		HELIUM_ASSERT( pObject );
	}

	if (load_properties_from_file && !object_creation_failure)
	{
		// Sanity checks for file load, then success path
		HELIUM_ASSERT( bytesRead == pRequest->asyncFileLoadBufferSize );
		if( IsInvalid( bytesRead ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader: Failed to read the contents of object file \"%s\" in async load request \"%d\".\n" ),
				object_file_path.c_str(),
				pRequest->asyncFileLoadId );
		}
		else if( bytesRead != pRequest->asyncFileLoadBufferSize )
		{
			HELIUM_TRACE(
				TraceLevels::Warning,
				( TXT( "LoosePackageLoader: Attempted to read %" ) PRIuSZ TXT( " bytes from object file \"%s\", " )
				TXT( "but only %" ) PRIuSZ TXT( " bytes were read.\n" ) ),
				pRequest->asyncFileLoadBufferSize,
				object_file_path.c_str(),
				bytesRead );
		}
		else
		{
			StaticMemoryStream archiveStream ( pRequest->pAsyncFileLoadBuffer, pRequest->asyncFileLoadBufferSize );

			HELIUM_TRACE(
				TraceLevels::Info,
				TXT( "LoosePackageLoader: Reading %s. pResolver = %x\n"), 
				object_file_path.c_str(),
				pRequest->pResolver);

			DynamicArray< Reflect::ObjectPtr > objects;
			objects.Push( pRequest->spObject.Get() ); // use existing objects
			Persist::ArchiveReaderJson::ReadFromStream( archiveStream, objects, pRequest->pResolver );
			HELIUM_ASSERT( objects[0].Get() == pRequest->spObject.Get() );
		}
	}

	if (load_properties_from_file)
	{
		DefaultAllocator().Free(pRequest->pAsyncFileLoadBuffer);
		pRequest->pAsyncFileLoadBuffer = NULL;
		pRequest->asyncFileLoadBufferSize = 0;
	}

	pRequest->flags |= LOAD_FLAG_PROPERTY_PRELOADED;

	if( object_creation_failure )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "LoosePackageLoader: Deserialization of object \"%s\" failed.\n" ),
			*rObjectData.objectPath.ToString() );
		
		pObject->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );
		pObject->ConditionalFinalizeLoad();

		pRequest->flags |= LOAD_FLAG_ERROR;
	}
	else if( !pObject->IsDefaultTemplate() )
	{
		// If the object is a resource (not including the default template object for resource types), attempt to begin
		// loading any existing persistent resource data stored in the object cache.
		Resource* pResource = Reflect::SafeCast< Resource >( pObject );
		if( pResource )
		{
			Name objectCacheName = Name( HELIUM_ASSET_CACHE_NAME );
			CacheManager& rCacheManager = CacheManager::GetStaticInstance();

			Cache* pCache = rCacheManager.GetCache( objectCacheName );
			HELIUM_ASSERT( pCache );
			pCache->EnforceTocLoad();

			const Cache::Entry* pEntry = pCache->FindEntry( rObjectData.objectPath, 0 );
			if( pEntry && pEntry->size != 0 )
			{
				HELIUM_ASSERT( IsInvalid( pRequest->persistentResourceDataLoadId ) );
				HELIUM_ASSERT( !pRequest->pCachedObjectDataBuffer );

				pRequest->pCachedObjectDataBuffer =
					static_cast< uint8_t* >( DefaultAllocator().Allocate( pEntry->size ) );
				HELIUM_ASSERT( pRequest->pCachedObjectDataBuffer );
				pRequest->cachedObjectDataBufferSize = pEntry->size;

				AsyncLoader& rAsyncLoader = AsyncLoader::GetStaticInstance();
				pRequest->persistentResourceDataLoadId = rAsyncLoader.QueueRequest(
					pRequest->pCachedObjectDataBuffer,
					pCache->GetCacheFileName(),
					pEntry->offset,
					pEntry->size );
				HELIUM_ASSERT( IsValid( pRequest->persistentResourceDataLoadId ) );
			}
		}
	}

	if( IsInvalid( pRequest->persistentResourceDataLoadId ) )
	{
		// No persistent resource data needs to be loaded.
		pObject->SetFlags( Asset::FLAG_PRELOADED );
		pRequest->flags |= LOAD_FLAG_PERSISTENT_RESOURCE_PRELOADED;
	}

	// Asset is now preloaded.
	return true;
}
/// Tick the object deserialization process for the given object load request.
///
/// @param[in] pRequest  Load request.
///
/// @return  True if the deserialization process has completed, false if it still needs time to process.
bool CachePackageLoader::TickDeserialize( LoadRequest* pRequest )
{
	HELIUM_ASSERT( pRequest );
	HELIUM_ASSERT( !( pRequest->flags & LOAD_FLAG_PRELOADED ) );

	HELIUM_ASSERT( !pRequest->spObject );

	const Cache::Entry* pCacheEntry = pRequest->pEntry;
	HELIUM_ASSERT( pCacheEntry );

	// Wait for the template and owner objects to load.
	AssetLoader* pAssetLoader = AssetLoader::GetInstance();
	HELIUM_ASSERT( pAssetLoader );

	if( IsValid( pRequest->ownerLoadIndex ) )
	{
		size_t ownerLoadId = pRequest->ownerLoadIndex;
		if( IsValid( ownerLoadId ) && !pAssetLoader->TryFinishLoad( ownerLoadId, pRequest->spOwner ) )
		{
			return false;
		}

		SetInvalid( pRequest->ownerLoadIndex );

		if( !pRequest->spOwner )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				"CachePackageLoader: Failed to load owner object for \"%s\".\n",
				*pCacheEntry->path.ToString() );

			DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
			pRequest->pAsyncLoadBuffer = NULL;

			pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

			return true;
		}
	}

	Asset* pOwner = pRequest->spOwner;

	HELIUM_ASSERT( !pOwner || pOwner->IsFullyLoaded() );
	
	Reflect::ObjectPtr cached_object = Cache::ReadCacheObjectFromBuffer(
		pRequest->pPropertyDataBegin, 
		0, 
		pRequest->pPropertyDataEnd - pRequest->pPropertyDataBegin, 
		pRequest->pResolver);

	AssetPtr assetPtr = Reflect::AssertCast<Asset>(cached_object);

	Asset::RenameParameters params;
	params.instanceIndex = -1;
	params.name = pCacheEntry->path.GetName();
	params.spOwner = pRequest->spOwner;
	assetPtr->Rename(params);

	pRequest->spObject = assetPtr;

	Asset *pObject = assetPtr;
	HELIUM_ASSERT( pObject );
		
	if (!cached_object.ReferencesObject())
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			"CachePackageLoader: Failed to deserialize object \"%s\".\n",
			*pCacheEntry->path.ToString() );

		pObject->SetFlags( Asset::FLAG_LINKED );
		pObject->ConditionalFinalizeLoad();

		pRequest->flags |= LOAD_FLAG_ERROR;
	}
	else
	{
		//cached_object->CopyTo(pObject);
				
		if( !pObject->IsDefaultTemplate() )
		{
			// Load persistent resource data.
			Resource* pResource = Reflect::SafeCast< Resource >( pObject );
			if( pResource )
			{
				Reflect::ObjectPtr cached_prd = Cache::ReadCacheObjectFromBuffer(
					pRequest->pPersistentResourceDataBegin, 
					0, 
					(pRequest->pPersistentResourceDataEnd - pRequest->pPersistentResourceDataBegin),
					pRequest->pResolver);

				if (!cached_prd.ReferencesObject())
				{
					HELIUM_TRACE(
						TraceLevels::Error,
						"CachePackageLoader: Failed to deserialize persistent resource data for \"%s\".\n",
						*pCacheEntry->path.ToString() );
				}
				else
				{
					pResource->LoadPersistentResourceObject(cached_prd);
				}
			}
		}
	}

	DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
	pRequest->pAsyncLoadBuffer = NULL;

	pObject->SetFlags( Asset::FLAG_PRELOADED );

	pRequest->flags |= LOAD_FLAG_PRELOADED;

	// Asset is now preloaded.
	return true;
}
Beispiel #4
0
void ForciblyFullyLoadedPackageManager::Tick()
{
	AssetLoader *pAssetLoader = AssetLoader::GetStaticInstance();

	// For each editable package
	for ( DynamicArray< ForciblyFullyLoadedPackage >::Iterator packageIter = m_ForciblyFullyLoadedPackages.Begin();
		packageIter != m_ForciblyFullyLoadedPackages.End(); ++packageIter)
	{
		ForciblyFullyLoadedPackage &package = *packageIter;

		// Load the package if we need to
		if ( Helium::IsValid< size_t >( package.m_PackageLoadId ) )
		{
			HELIUM_ASSERT( package.m_Assets.IsEmpty() );
			HELIUM_ASSERT( package.m_AssetLoadIds.IsEmpty() );
			HELIUM_ASSERT( package.m_AssetPaths.IsEmpty() );
			HELIUM_ASSERT( !package.m_Package );

			AssetPtr packagePtr;
			if ( pAssetLoader->TryFinishLoad( package.m_PackageLoadId, packagePtr ) )
			{
				// Load request is finished.
				package.m_PackageLoadId = Helium::Invalid< size_t >();
				package.m_Package = Reflect::AssertCast<Package>(packagePtr);

				if ( package.m_Package )
				{
					if ( !package.m_Package->GetAllFlagsSet( Asset::FLAG_EDITOR_FORCIBLY_LOADED ) )
					{
						// Package loaded successfully, queue load requests for all children
						package.m_Package->SetFlags( Asset::FLAG_EDITOR_FORCIBLY_LOADED );
						e_AssetForciblyLoadedEvent.Raise( AssetEventArgs( package.m_Package ) );
					}

					PackageLoader *pLoader = package.m_Package->GetLoader();
					pLoader->EnumerateChildren( package.m_AssetPaths );

					package.m_Assets.Resize( package.m_AssetPaths.GetSize() );
					package.m_AssetLoadIds.Resize( package.m_AssetPaths.GetSize() );

					DynamicArray< AssetPath >::Iterator assetPathIter = package.m_AssetPaths.Begin();
					DynamicArray< size_t >::Iterator assetLoadIdIter = package.m_AssetLoadIds.Begin();

					int i = 0;
					for ( ; assetPathIter != package.m_AssetPaths.End(); ++assetPathIter, ++assetLoadIdIter )
					{
						*assetLoadIdIter = pAssetLoader->BeginLoadObject( *assetPathIter );
						HELIUM_ASSERT( !package.m_Assets[i++] );
					}
				}
				else
				{
					HELIUM_TRACE(
						TraceLevels::Warning,
						"Failed to load package '%s' for editor.",
						*package.m_PackagePath.ToString());
				}
			}
		}
	}

	// For each editable package
	for ( DynamicArray< ForciblyFullyLoadedPackage >::Iterator packageIter = m_ForciblyFullyLoadedPackages.Begin();
		packageIter != m_ForciblyFullyLoadedPackages.End(); ++packageIter)
	{
		ForciblyFullyLoadedPackage &package = *packageIter;

		// If the package is loaded
		if ( package.m_Package )
		{
			// Load the child assets if we need to
			for ( int i = 0; i < package.m_AssetPaths.GetSize(); ++i )
			{
				if ( Helium::IsValid<size_t>( package.m_AssetLoadIds[i] ) )
				{
					HELIUM_ASSERT( !package.m_Assets[i] );
					if ( pAssetLoader->TryFinishLoad( package.m_AssetLoadIds[i], package.m_Assets[i] ) )
					{
						package.m_AssetLoadIds[i] = Invalid< size_t >();

						if ( package.m_Assets[i] )
						{
							// Asset loaded successfully
							if ( !package.m_Assets[i]->IsPackage() && !package.m_Assets[i]->GetAllFlagsSet( Asset::FLAG_EDITOR_FORCIBLY_LOADED ) )
							{
								package.m_Assets[i]->SetFlags( Asset::FLAG_EDITOR_FORCIBLY_LOADED );
								e_AssetForciblyLoadedEvent.Raise( AssetEventArgs( package.m_Assets[i] ) );
							}
						}
						else
						{
							HELIUM_TRACE(
								TraceLevels::Warning,
								"Failed to asset '%s' for editor.",
								*package.m_PackagePath.ToString());
						}
					}
					else
					{
						HELIUM_ASSERT( !package.m_Assets[i] );
					}

					if ( Helium::IsValid<size_t>( package.m_AssetLoadIds[i] ) )
					{
						HELIUM_ASSERT( !package.m_Assets[i] );
					}
				}
			}
		}
	}
}
/// @copydoc PackageLoader::TryFinishLoadObject()
bool CachePackageLoader::TryFinishLoadObject( size_t requestId, AssetPtr& rspObject )
{
	HELIUM_ASSERT( requestId < m_loadRequests.GetSize() );
	HELIUM_ASSERT( m_loadRequests.IsElementValid( requestId ) );

	LoadRequest* pRequest = m_loadRequests[ requestId ];
	HELIUM_ASSERT( pRequest );
	if( !( pRequest->flags & LOAD_FLAG_PRELOADED ) )
	{
		return false;
	}

	// Sync on template and owner dependencies.
	AssetLoader* pAssetLoader = AssetLoader::GetInstance();
	HELIUM_ASSERT( pAssetLoader );

	if( IsValid( pRequest->ownerLoadIndex ) )
	{
		size_t linkLoadId = pRequest->ownerLoadIndex;
		if( IsValid( linkLoadId ) && !pAssetLoader->TryFinishLoad( linkLoadId, pRequest->spOwner ) )
		{
			return false;
		}

		SetInvalid( pRequest->ownerLoadIndex );
	}

	rspObject = pRequest->spObject;
	Asset* pObject = rspObject;
	if( pObject && ( pRequest->flags & LOAD_FLAG_ERROR ) )
	{
		pObject->SetFlags( Asset::FLAG_BROKEN );
	}

	if ( pObject->IsPackage() )
	{
		Package *pPackage = Reflect::AssertCast<Package>( pObject );
		pPackage->SetLoader( this );
	}

	pRequest->spObject.Release();

	HELIUM_ASSERT( IsInvalid( pRequest->asyncLoadId ) );
	HELIUM_ASSERT( !pRequest->pAsyncLoadBuffer );

	//pRequest->spTemplate.Release();
	pRequest->spOwner.Release();

	HELIUM_ASSERT( IsInvalid( pRequest->ownerLoadIndex ) );
	//HELIUM_ASSERT( IsInvalid( pRequest->templateLoadIndex ) );

	HELIUM_ASSERT( pObject || pRequest->pEntry );
	HELIUM_TRACE(
		TraceLevels::Debug,
		"CachePackageLoader::TryFinishLoadObject(): Load request for \"%s\" (ID: %" PRIuSZ ") synced.\n",
		*( pObject ? pObject->GetPath() : pRequest->pEntry->path ).ToString(),
		requestId );

	m_loadRequests.Remove( requestId );
	m_loadRequestPool.Release( pRequest );

	return true;
}