Exemplo n.º 1
0
/// Search for the resource handler for the specified type.
///
/// @param[in] pType  Resource type.
///
/// @return  Resource handler for the given type if found, null if no resource handler was found.
ResourceHandler* ResourceHandler::FindResourceHandlerForType( const GameObjectType* pType )
{
    HELIUM_ASSERT( pType );

    const GameObjectType* pResourceHandlerType = GetStaticType();
    HELIUM_ASSERT( pResourceHandlerType );

    GameObjectType::ConstIterator typeEnd = GameObjectType::GetTypeEnd();
    for( GameObjectType::ConstIterator typeIterator = GameObjectType::GetTypeBegin(); typeIterator != typeEnd; ++typeIterator )
    {
        const GameObjectType& rType = *typeIterator;
        if( &rType != pResourceHandlerType && rType.GetClass()->IsType( pResourceHandlerType->GetClass() ) )
        {
            ResourceHandler* pHandler = Reflect::AssertCast< ResourceHandler >( rType.GetTemplate() );
            HELIUM_ASSERT( pHandler );
            if( pHandler->GetResourceType() == pType )
            {
                return pHandler;
            }
        }
    }

    return NULL;
}
Exemplo n.º 2
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 );
}