/// Recursive function for resolving a package request.
///
/// @param[out] rspPackage   Resolved package.
/// @param[in]  packagePath  Package object path.
void CachePackageLoader::ResolvePackage( AssetPtr& rspPackage, AssetPath packagePath )
{
	HELIUM_ASSERT( !packagePath.IsEmpty() );

	rspPackage = Asset::FindObject( packagePath );
	if( !rspPackage )
	{
		AssetPtr spParent;
		AssetPath parentPath = packagePath.GetParent();
		if( !parentPath.IsEmpty() )
		{
			ResolvePackage( spParent, parentPath );
			HELIUM_ASSERT( spParent );
		}

		HELIUM_VERIFY( Asset::CreateObject(
			rspPackage,
			Package::GetStaticType(),
			packagePath.GetName(),
			spParent ) );
		HELIUM_ASSERT( rspPackage );
		HELIUM_ASSERT( rspPackage->IsA( Package::GetStaticType()->GetMetaClass() ) );
	}

	rspPackage->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED | Asset::FLAG_LOADED );
}
Esempio n. 2
0
/// Find an object based on its path name.
///
/// @param[in] path  FilePath of the object to locate.
///
/// @return  Pointer to the object if found, null pointer if not found.
Asset* Asset::FindObject( AssetPath path )
{
	// Make sure the path isn't empty.
	if( path.IsEmpty() )
	{
		return NULL;
	}

	// Assemble a list of object names and instance indices, from the top level on down.
	size_t pathDepth = 0;
	size_t packageDepth = 0;
	for( AssetPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() )
	{
		++pathDepth;

		if( testPath.IsPackage() )
		{
			++packageDepth;
		}
	}

	StackMemoryHeap<>& rStackHeap = ThreadLocalStackAllocator::GetMemoryHeap();
	StackMemoryHeap<>::Marker stackMarker( rStackHeap );

	Name* pPathNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * pathDepth ) );
	HELIUM_ASSERT( pPathNames );

	uint32_t* pInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * pathDepth ) );
	HELIUM_ASSERT( pInstanceIndices );

	size_t pathIndex = pathDepth;
	for( AssetPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() )
	{
		HELIUM_ASSERT( pathIndex != 0 );
		--pathIndex;

		pPathNames[ pathIndex ] = testPath.GetName();
		pInstanceIndices[ pathIndex ] = testPath.GetInstanceIndex();
	}

	HELIUM_ASSERT( pathIndex == 0 );

	// Search from the root.
	return FindChildOf( NULL, pPathNames, pInstanceIndices, pathDepth, packageDepth );
}
Esempio n. 3
0
/// Initialize this manager.
///
/// @return  True if this manager was initialized successfully, false if not.
///
/// @see Shutdown()
bool WorldManager::Initialize()
{
	HELIUM_ASSERT( !m_spRootSceneDefinitionsPackage );

	// Create the world package first.
	// XXX TMC: Note that we currently assume that the world package has no parents, so we don't need to handle
	// recursive package creation.  If we want to move the world package to a subpackage, this will need to be
	// updated accordingly.
	AssetPath rootSceneDefinitionsPackagePath = GetRootSceneDefinitionPackagePath();
	HELIUM_ASSERT( !rootSceneDefinitionsPackagePath.IsEmpty() );
	HELIUM_ASSERT( rootSceneDefinitionsPackagePath.GetParent().IsEmpty() );
	bool bCreateResult = Asset::Create< Package >( m_spRootSceneDefinitionsPackage, rootSceneDefinitionsPackagePath.GetName(), NULL );
	HELIUM_ASSERT( bCreateResult );
	if( !bCreateResult )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "WorldManager::Initialize(): Failed to create world definition package \"%s\".\n" ),
			*rootSceneDefinitionsPackagePath.ToString() );

		return false;
	}

	HELIUM_ASSERT( m_spRootSceneDefinitionsPackage );

	// Reset frame timings.
	m_actualFrameTickCount = 0;
	m_frameTickCount = 0;
	m_frameDeltaTickCount = 0;
	m_frameDeltaSeconds = 0.0f;

	// First frame still needs to be processed.
	m_bProcessedFirstFrame = false;

	return true;
}
Esempio n. 4
0
/// Begin asynchronous loading of an object.
///
/// @param[in] path  Asset path.
///
/// @return  ID for the load request if started successfully, invalid index if not.
///
/// @see TryFinishLoad(), FinishLoad()
size_t AssetLoader::BeginLoadObject( AssetPath path, bool forceReload )
{
	HELIUM_TRACE( TraceLevels::Info, TXT(" AssetLoader::BeginLoadObject - Loading path %s\n"), *path.ToString() );
	HELIUM_ASSERT( !path.GetName().IsEmpty() );

	// Search for an existing load request with the given path.
	ConcurrentHashMap< AssetPath, LoadRequest* >::ConstAccessor requestConstAccessor;
	if( m_loadRequestMap.Find( requestConstAccessor, path ) )
	{
		LoadRequest* pRequest = requestConstAccessor->Second();
		HELIUM_ASSERT( pRequest );
		AtomicIncrementRelease( pRequest->requestCount );

		// We can release now, as the request shouldn't get released now that we've incremented its reference count.
		requestConstAccessor.Release();

		return m_loadRequestPool.GetIndex( pRequest );
	}

	Asset *pAsset = NULL;

	if ( !forceReload )
	{
		pAsset = Asset::Find<Asset>( path );
		if ( pAsset && !pAsset->GetAllFlagsSet( Asset::FLAG_LOADED ) )
		{
			pAsset = NULL;
		}
	}


	PackageLoader *pPackageLoader = 0;
	if ( pAsset )
	{
			HELIUM_TRACE(
				TraceLevels::Info,
				TXT( "AssetLoader::BeginLoadObject(): Object \"%s\" already loaded.\n" ),
				*path.ToString() );
	} 
	else
	{
		// Get the package loader to use for the given object.
		pPackageLoader = GetPackageLoader( path );
		if( !pPackageLoader )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "AssetLoader::BeginLoadObject(): Failed to locate package loader for \"%s\".\n" ),
				*path.ToString() );

			return Invalid< size_t >();
		}
	}

	// Add the load request.
	LoadRequest* pRequest = m_loadRequestPool.Allocate();
	pRequest->path = path;
	pRequest->pPackageLoader = pPackageLoader;
	SetInvalid( pRequest->packageLoadRequestId );
	pRequest->stateFlags = pAsset ? 
		(pAsset->GetFlags() & Asset::FLAG_BROKEN ? LOAD_FLAG_FULLY_LOADED | LOAD_FLAG_ERROR : LOAD_FLAG_FULLY_LOADED ) : 
		0;
	pRequest->requestCount = 1;
	HELIUM_ASSERT( !pRequest->spObject );
	pRequest->spObject = pAsset;
	pRequest->forceReload = forceReload;

	ConcurrentHashMap< AssetPath, LoadRequest* >::Accessor requestAccessor;
	if( m_loadRequestMap.Insert( requestAccessor, KeyValue< AssetPath, LoadRequest* >( path, pRequest ) ) )
	{
		// New load request was created, so tick it once to get the load process running.
		requestAccessor.Release();
		TickLoadRequest( pRequest );
	}
	else
	{
		// A matching request was added while we were building our request, so reuse it.
		m_loadRequestPool.Release( pRequest );

		pRequest = requestAccessor->Second();
		HELIUM_ASSERT( pRequest );
		AtomicIncrementRelease( pRequest->requestCount );

		// We can release now, as the request shouldn't get released now that we've incremented its reference count.
		requestAccessor.Release();
	}

	return m_loadRequestPool.GetIndex( pRequest );
}
Esempio n. 5
0
/// Set this path to the combination of two paths.
///
/// @param[in] pRootPath  Root portion of the path.
/// @param[in] subPath    Sub-path component.
///
/// @return  True if the paths could be joined into a valid path (to which this path was set), false if joining was
///          invalid.
bool AssetPath::Join( const char* pRootPath, AssetPath subPath )
{
	if( !pRootPath || pRootPath[ 0 ] == TXT( '\0' ) )
	{
		m_pEntry = subPath.m_pEntry;

		return true;
	}

	// Parse the root path into a series of names.
	StackMemoryHeap<>& rStackHeap = ThreadLocalStackAllocator::GetMemoryHeap();
	StackMemoryHeap<>::Marker stackMarker( rStackHeap );

	Name* pRootPathNames;
	uint32_t* pRootPathIndices;
	size_t rootPathNameCount;
	size_t rootPathPackageCount;
	if( !Parse( pRootPath, rStackHeap, pRootPathNames, pRootPathIndices, rootPathNameCount, rootPathPackageCount ) )
	{
		return false;
	}

	if( rootPathNameCount != rootPathPackageCount )
	{
		AssetPath testSubPathComponent = subPath.GetParent();
		AssetPath subPathComponent;
		do
		{
			subPathComponent = testSubPathComponent;
			testSubPathComponent = testSubPathComponent.GetParent();

			if( subPathComponent.IsPackage() )
			{
				HELIUM_TRACE(
					TraceLevels::Error,
					( TXT( "AssetPath::Join(): Cannot combine \"%s\" and \"%s\" (second path is rooted in a " )
					TXT( "package, while the first path ends in an object).\n" ) ),
					pRootPath,
					*subPath.ToString() );

				return false;
			}
		} while( !testSubPathComponent.IsEmpty() );
	}

	// Assemble the list of path names in reverse order for performing the object path lookup/add.
	size_t nameCount = rootPathNameCount;
	size_t packageCount = rootPathPackageCount;

	AssetPath testPath;

	for( testPath = subPath; !testPath.IsEmpty(); testPath = testPath.GetParent() )
	{
		++nameCount;
		if( testPath.IsPackage() )
		{
			++packageCount;
		}
	}

	Name* pEntryNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * nameCount ) );
	HELIUM_ASSERT( pEntryNames );

	uint32_t* pInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * nameCount ) );
	HELIUM_ASSERT( pInstanceIndices );

	Name* pCurrentName = pEntryNames;
	uint32_t* pCurrentIndex = pInstanceIndices;

	for( testPath = subPath; !testPath.IsEmpty(); testPath = testPath.GetParent() )
	{
		*pCurrentName = testPath.GetName();
		*pCurrentIndex = testPath.GetInstanceIndex();
		++pCurrentName;
		++pCurrentIndex;
	}

	ArrayCopy( pCurrentName, pRootPathNames, rootPathNameCount );
	ArrayCopy( pCurrentIndex, pRootPathIndices, rootPathNameCount );

	// Set the path.
	Set( pEntryNames, pInstanceIndices, nameCount, packageCount );

	return true;
}