/// 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
/// Set this object path based on the given parameters.
///
/// @param[in] pNames            Array of object names in the path, starting from the bottom level on up.
/// @param[in] pInstanceIndices  Array of object instance indices in the path, starting from the bottom level on up.
/// @param[in] nameCount         Number of object names.
/// @param[in] packageCount      Number of object names that are packages.
void AssetPath::Set( const Name* pNames, const uint32_t* pInstanceIndices, size_t nameCount, size_t packageCount )
{
	HELIUM_ASSERT( pNames );
	HELIUM_ASSERT( pInstanceIndices );
	HELIUM_ASSERT( nameCount != 0 );

	// Set up the entry for this path.
	Entry entry;
	entry.pParent = NULL;
	entry.name = pNames[ 0 ];
	entry.instanceIndex = pInstanceIndices[ 0 ];
	entry.bPackage = ( nameCount <= packageCount );

	if( nameCount > 1 )
	{
		size_t parentNameCount = nameCount - 1;

		AssetPath parentPath;
		parentPath.Set( pNames + 1, pInstanceIndices + 1, parentNameCount, Min( parentNameCount, packageCount ) );
		entry.pParent = parentPath.m_pEntry;
		HELIUM_ASSERT( entry.pParent );
	}

	// Look up/add the entry.
	m_pEntry = Add( entry );
	HELIUM_ASSERT( m_pEntry );
}
Esempio n. 3
0
void Helium::LooseAssetLoader::EnumerateRootPackages( DynamicArray< AssetPath > &packagePaths )
{
	FilePath dataDirectory;
	FileLocations::GetDataDirectory( dataDirectory );

	DirectoryIterator packageDirectory( dataDirectory );
	for( ; !packageDirectory.IsDone(); packageDirectory.Next() )
	{
		if (packageDirectory.GetItem().m_Path.IsDirectory())
		{
			AssetPath path;

			//std::string filename = packageDirectory.GetItem().m_Path.Parent();
			std::vector< std::string > filename = packageDirectory.GetItem().m_Path.DirectoryAsVector();
			HELIUM_ASSERT(!filename.empty());
			std::string directory = filename.back();

			if (directory.size() <= 0)
			{
				continue;
			}
			path.Set( Name( directory.c_str() ), true, AssetPath(NULL_NAME) );

			packagePaths.Add( path );
		}

	}
}
Esempio n. 4
0
		inline std::string getPrefix( AssetPath p ) {
			unsigned s = p.find_last_of("/\\");
			if( s == std::string::npos )
				s = 0;
			else
				s++;
			
			return p.substr(s,3);
		}
Esempio n. 5
0
/// Get the path to the package containing all world instances.
///
/// @return  World package path.
AssetPath WorldManager::GetRootSceneDefinitionPackagePath() const
{
	static AssetPath worldPackagePath;
	if( worldPackagePath.IsEmpty() )
	{
		HELIUM_VERIFY( worldPackagePath.Set( TXT( "/Worlds" ) ) );
	}

	return worldPackagePath;
}
Esempio n. 6
0
bool ProjectViewModel::IsContainer( const wxDataViewItem& item ) const
{
	// root node can have children
	if ( !item.IsOk() )
	{
		return true;
	}

	AssetPath *node = static_cast< AssetPath* >( item.GetID() );
	return node ? node->IsPackage() : false;
}
Esempio n. 7
0
		void asyncLoad( AssetPath path, AssetPromisePtr pr, AssetContentPtr c, Progress::Work w ) {
			try {
				{
					// TODO: Do this properly...
					// Get the contents of the file
					std::ifstream fs(path.c_str(), std::ios::binary);	
					if( !fs.is_open() )
						BOOST_THROW_EXCEPTION( InexistentAssetPathException(path) );
					fs.seekg(0,std::ios::end);
					std::vector<char> buf((unsigned)fs.tellg() + 1);
					fs.seekg(0,std::ios::beg);
					fs.read(&buf[0],buf.capacity());
					buf.resize((unsigned)fs.gcount());
					fs.close();
					// call the loading method on the AssetContent
					c->asyncLoad(buf);
				}
				
				mngr.prog_.makeProgress(w);

				// after loading is done, set the promise value to the content
				pr->set_value(c);
			} catch( ... ) {
				// transfer exceptions to the main thread
				pr->set_exception(boost::current_exception());
			}
			boost::this_thread::yield();
		}
Esempio n. 8
0
int64_t AssetLoader::GetAssetFileTimestamp( const AssetPath &path )
{
	Package *pPackage = Asset::Find<Package>( path.GetParent() );
	HELIUM_ASSERT( pPackage );

	PackageLoader *pLoader = pPackage->GetLoader();
	HELIUM_ASSERT( pLoader );

	return pLoader->GetAssetFileSystemTimestamp( path );
}
Esempio n. 9
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. 10
0
int64_t LoosePackageLoader::GetAssetFileSystemTimestamp( const AssetPath &path ) const
{
	size_t index = FindObjectByName( path.GetRootName() );
	HELIUM_ASSERT( index < m_objects.GetSize() );
	if ( index < m_objects.GetSize() )
	{
		return m_objects[ index ].fileTimeStamp;
	}
	else
	{
		return 0;
	}
}
Esempio n. 11
0
bool Helium::AssetResolver::Resolve( const Name& identity, Reflect::ObjectPtr& pointer, const Reflect::MetaClass* pointerClass )
{
	// Paths begin with /
	if (!identity.IsEmpty() && (*identity)[0] == '/')
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Resolving object [%s]\n" ), identity.Get() );

		AssetPath p;
		p.Set(*identity);

		size_t loadRequestId = AssetLoader::GetStaticInstance()->BeginLoadObject(p);
		m_Fixups.Push( Fixup( pointer, pointerClass, loadRequestId ) );

		return true;
	}
	else
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Deferring resolution of [%s] to archive\n" ), identity.Get() );
	}

	return false;
}
Esempio n. 12
0
TEST(Engine, PackageObjectTest)
{
    {
        AssetPath testPath;
        HELIUM_VERIFY( testPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "EngineTest" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "TestObject" ) ) );

        AssetPtr spObject;
        HELIUM_VERIFY( gAssetLoader->LoadObject( testPath, spObject ) );
        HELIUM_ASSERT( spObject );

        Package* pTestPackageCast = Reflect::SafeCast< Package >( spObject.Get() );
        HELIUM_ASSERT( !pTestPackageCast );
        HELIUM_UNREF( pTestPackageCast );

        // The following line should not compile...
        //            Animation* pTestAnimationCast = Reflect::SafeCast< Animation >( pTestPackageCast );
        //            HELIUM_UNREF( pTestAnimationCast );

        Asset* pTestObjectCast = Reflect::SafeCast< Asset >( spObject.Get() );
        HELIUM_ASSERT( pTestObjectCast );
        HELIUM_UNREF( pTestObjectCast );
    }
}
Esempio n. 13
0
bool Helium::AssetResolver::Resolve( const Name& identity, Reflect::ObjectPtr& pointer, const Reflect::MetaClass* pointerClass )
{
	// Paths begin with /
	if (!identity.IsEmpty() && (*identity)[0] == '/')
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Resolving object [%s]\n" ), identity.Get() );

		AssetPath p;
		p.Set(*identity);

		size_t loadRequestId = AssetLoader::GetStaticInstance()->BeginLoadObject(p);
		m_Fixups.Push( Fixup( pointer, pointerClass, loadRequestId ) );

		return true;
	}
	else
	{
#if HELIUM_TOOLS
		// Some extra checking to make friendly error messages
		String str ( identity.Get() );
		uint32_t index = Invalid< uint32_t >();
		int parseSuccessful = str.Parse( "%d", &index );

		if (!parseSuccessful)
		{
			HELIUM_TRACE(
				TraceLevels::Warning,
				"AssetResolver::Resolve - Identity '%s' is not a number, but doesn't start with '/'. If this is a path, it must begin with '/'!\n", 
				*str);
		}
#endif

		HELIUM_TRACE( TraceLevels::Debug, TXT( "Deferring resolution of [%s] to archive\n" ), identity.Get() );
	}

	return false;
}
Esempio n. 14
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. 15
0
/// Update property preloading for the given object load request.
///
/// @param[in] pRequest  Load request to update.
///
/// @return  True if preloading still needs processing, false if it is complete.
bool AssetLoader::TickPreload( LoadRequest* pRequest )
{
	HELIUM_ASSERT( pRequest );
	HELIUM_ASSERT( !( pRequest->stateFlags & ( LOAD_FLAG_LINKED | LOAD_FLAG_PRECACHED | LOAD_FLAG_LOADED ) ) );

	PackageLoader* pPackageLoader = pRequest->pPackageLoader;
	HELIUM_ASSERT( pPackageLoader );

	if( IsInvalid( pRequest->packageLoadRequestId ) )
	{
		if( !pPackageLoader->TryFinishPreload() )
		{
			// Still waiting for package loader preload.
			return false;
		}

		// Add an object load request.
		AssetPath path = pRequest->path;
		pRequest->packageLoadRequestId = pPackageLoader->BeginLoadObject( path, &pRequest->resolver );
		if( IsInvalid( pRequest->packageLoadRequestId ) )
		{
			pRequest->spObject = Asset::FindObject( path );
			Asset* pObject = pRequest->spObject;
			if( pObject )
			{
				HELIUM_TRACE(
					TraceLevels::Info,
					TXT( "AssetLoader: Asset \"%s\" is not serialized, but was found in memory.\n" ),
					*path.ToString() );

				// Make sure the object is preloaded and linked, but still perform resource caching and load
				// finalization if necessary.
				pObject->SetFlags( Asset::FLAG_PRELOADED | Asset::FLAG_LINKED );

				AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRELOADED | LOAD_FLAG_LINKED );

				return true;
			}

			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "AssetLoader: Asset \"%s\" is not serialized and does not exist in memory.\n" ),
				*path.ToString() );

			AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_FULLY_LOADED | LOAD_FLAG_ERROR );

			return true;
		}
	}

	HELIUM_ASSERT( IsValid( pRequest->packageLoadRequestId ) );

	bool bFinished = pPackageLoader->TryFinishLoadObject(
		pRequest->packageLoadRequestId,
		pRequest->spObject );
	if( !bFinished )
	{
		// Still waiting for object to load.
		return false;
	}

	// Preload complete.
	SetInvalid( pRequest->packageLoadRequestId );

	AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRELOADED );

	return true;
}
Esempio n. 16
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 )
{
	HELIUM_TRACE( TraceLevels::Info, TXT(" AssetLoader::BeginLoadObject - Loading path %s\n"), *path.ToString() );

	// 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 = 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;

	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. 17
0
/// Deserialize the link tables for an object load.
///
/// @param[in] pRequest  Load request data.
bool CachePackageLoader::ReadCacheData( LoadRequest* pRequest )
{
	HELIUM_ASSERT( pRequest );

	uint8_t* pBufferCurrent = pRequest->pAsyncLoadBuffer;
	uint8_t* pPropertyDataEnd = pRequest->pPropertyDataEnd;
	HELIUM_ASSERT( pBufferCurrent );
	HELIUM_ASSERT( pPropertyDataEnd );
	HELIUM_ASSERT( pBufferCurrent <= pPropertyDataEnd );

	// We know the owner's path immediately just by looking at the path we're currently loading
	AssetPath parentPath = pRequest->pEntry->path.GetParent();
	pRequest->ownerLoadIndex = AssetLoader::GetInstance()->BeginLoadObject( parentPath );

	if (IsInvalid<size_t>(pRequest->ownerLoadIndex))
	{
		HELIUM_TRACE(
			TraceLevels::Debug,
			"CachePackageLoader: Failed to begin loading owning asset '%s' for '%s'.\n",
			*parentPath.ToString(),
			*pRequest->pEntry->path.ToString());
	}

	// Scan the property stream.. another null terminated string with character count first
	uint32_t propertyStreamSize = 0;
	if( pBufferCurrent + sizeof( propertyStreamSize ) > pPropertyDataEnd )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			"CachePackageLoader: End of buffer reached when attempting to deserialize \"%s\".\n",
			*pRequest->pEntry->path.ToString() );

		return false;
	}

	MemoryCopy( &propertyStreamSize, pBufferCurrent, sizeof( propertyStreamSize ) );
	pBufferCurrent += sizeof( propertyStreamSize );

	if( propertyStreamSize > static_cast< size_t >( pPropertyDataEnd - pBufferCurrent ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			"CachePackageLoader: Property stream size (%" PRIu32 " bytes) for \"%s\" exceeds the amount of data cached.  Value will be clamped.\n",
			propertyStreamSize,
			*pRequest->pEntry->path.ToString() );

		propertyStreamSize = static_cast< uint32_t >( pPropertyDataEnd - pBufferCurrent );
	}

	pRequest->pPropertyDataBegin = pBufferCurrent;
	pPropertyDataEnd = pBufferCurrent + propertyStreamSize;
	pRequest->pPropertyDataEnd = pPropertyDataEnd;

	// Verify that it's null terminated
	HELIUM_ASSERT( pRequest->pPropertyDataEnd[-1] == 0);

	// Adjust the end of the persistent resource data stream to account for the resource sub-data count padded on
	// the end (note that non-resources will not have this padding). The count is at the END of the buffer, and
	// if we have enough room for a size left, then assume persistant resource starts immediately after the property
	// data ends, and ends at the count.
	if( pRequest->pPersistentResourceDataEnd - pPropertyDataEnd >= sizeof( uint32_t ) )
	{
		pRequest->pPersistentResourceDataBegin = pPropertyDataEnd;
		pRequest->pPersistentResourceDataEnd -= sizeof( uint32_t );

		HELIUM_ASSERT( pRequest->pPersistentResourceDataEnd[-1] == 0 );
	}
	else
	{
		pRequest->pPersistentResourceDataBegin = pPropertyDataEnd;
		pRequest->pPersistentResourceDataEnd = pPropertyDataEnd;
	}

	return true;
}
Esempio n. 18
0
int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nCmdShow )
{
	ForceLoadComponentsDll();

#if HELIUM_TOOLS
	ForceLoadEditorSupportDll();
#endif

	HELIUM_TRACE_SET_LEVEL( TraceLevels::Debug );

	Timer::StaticInitialize();
	
#if !HELIUM_RELEASE && !HELIUM_PROFILE
	Helium::InitializeSymbols();
#endif

	AsyncLoader::GetStaticInstance().Initialize();

	FilePath baseDirectory;
	if ( !FileLocations::GetBaseDirectory( baseDirectory ) )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "Could not get base directory." ) );
		return -1;
	}

	HELIUM_VERIFY( CacheManager::InitializeStaticInstance( baseDirectory ) );
	Helium::Bullet::Initialize();

	int resultCode = -1;

	{
	Reflect::Initialize();

	Helium::Components::Initialize();
	
	Helium::TaskScheduler::CalculateSchedule();

#if HELIUM_TOOLS
#endif

	InitEngineJobsDefaultHeap();
	InitGraphicsJobsDefaultHeap();
	InitTestJobsDefaultHeap();

#if HELIUM_TOOLS
	//HELIUM_VERIFY( LooseAssetLoader::InitializeStaticInstance() );
	HELIUM_VERIFY( LooseAssetLoader::InitializeStaticInstance() );

	AssetPreprocessor* pAssetPreprocessor = AssetPreprocessor::CreateStaticInstance();
	HELIUM_ASSERT( pAssetPreprocessor );
	PlatformPreprocessor* pPlatformPreprocessor = new PcPreprocessor;
	HELIUM_ASSERT( pPlatformPreprocessor );
	pAssetPreprocessor->SetPlatformPreprocessor( Cache::PLATFORM_PC, pPlatformPreprocessor );
#else
	HELIUM_VERIFY( CacheAssetLoader::InitializeStaticInstance() );
#endif

#if !GTEST
	AssetLoader* gAssetLoader = NULL;
#endif

	gAssetLoader = AssetLoader::GetStaticInstance();
	HELIUM_ASSERT( gAssetLoader );

	Config& rConfig = Config::GetStaticInstance();
	rConfig.BeginLoad();
	while( !rConfig.TryFinishLoad() )
	{
		gAssetLoader->Tick();
	}

#if HELIUM_TOOLS
	ConfigPc::SaveUserConfig();
#endif

	uint32_t displayWidth;
	uint32_t displayHeight;
	//bool bFullscreen;
	bool bVsync;
	
	{
		StrongPtr< GraphicsConfig > spGraphicsConfig(
			rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) );
		HELIUM_ASSERT( spGraphicsConfig );
		displayWidth = spGraphicsConfig->GetWidth();
		displayHeight = spGraphicsConfig->GetHeight();
		//bFullscreen = spGraphicsConfig->GetFullscreen();
		bVsync = spGraphicsConfig->GetVsync();
	}

	WNDCLASSEXW windowClass;
	windowClass.cbSize = sizeof( windowClass );
	windowClass.style = 0;
	windowClass.lpfnWndProc = WindowProc;
	windowClass.cbClsExtra = 0;
	windowClass.cbWndExtra = 0;
	windowClass.hInstance = hInstance;
	windowClass.hIcon = NULL;
	windowClass.hCursor = NULL;
	windowClass.hbrBackground = NULL;
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = L"HeliumTestAppClass";
	windowClass.hIconSm = NULL;
	HELIUM_VERIFY( RegisterClassEx( &windowClass ) );

	WindowData windowData;
	windowData.hMainWnd = NULL;
	windowData.hSubWnd = NULL;
	windowData.bProcessMessages = true;
	windowData.bShutdownRendering = false;
	windowData.resultCode = 0;

	DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
	RECT windowRect;

	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = static_cast< LONG >( displayWidth );
	windowRect.bottom = static_cast< LONG >( displayHeight );
	HELIUM_VERIFY( AdjustWindowRect( &windowRect, dwStyle, FALSE ) );

	HWND hMainWnd = ::CreateWindowW(
		L"HeliumTestAppClass",
		L"Helium TestApp",
		dwStyle,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL );
	HELIUM_ASSERT( hMainWnd );

	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = static_cast< LONG >( displayWidth );
	windowRect.bottom = static_cast< LONG >( displayHeight );
	HELIUM_VERIFY( AdjustWindowRect( &windowRect, dwStyle, FALSE ) );
#if MULTI_WINDOW
	HWND hSubWnd = ::CreateWindowW(
		L"HeliumTestAppClass",
		L"Helium TestApp (second view)",
		dwStyle,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL );
	HELIUM_ASSERT( hSubWnd );
#endif

	windowData.hMainWnd = hMainWnd;
	SetWindowLongPtr( hMainWnd, GWLP_USERDATA, reinterpret_cast< LONG_PTR >( &windowData ) );
	ShowWindow( hMainWnd, nCmdShow );
	UpdateWindow( hMainWnd );
#if MULTI_WINDOW
	windowData.hSubWnd = hSubWnd;
	SetWindowLongPtr( hSubWnd, GWLP_USERDATA, reinterpret_cast< LONG_PTR >( &windowData ) );
	ShowWindow( hSubWnd, nCmdShow );
	UpdateWindow( hSubWnd );
#endif

	HELIUM_VERIFY( D3D9Renderer::CreateStaticInstance() );

	Renderer* pRenderer = Renderer::GetStaticInstance();
	HELIUM_ASSERT( pRenderer );
	pRenderer->Initialize();

	Renderer::ContextInitParameters contextInitParams;

	contextInitParams.pWindow = hMainWnd;
	contextInitParams.displayWidth = displayWidth;
	contextInitParams.displayHeight = displayHeight;
	contextInitParams.bVsync = bVsync;
	HELIUM_VERIFY( pRenderer->CreateMainContext( contextInitParams ) );
#if MULTI_WINDOW
	contextInitParams.pWindow = hSubWnd;
	RRenderContextPtr spSubRenderContext = pRenderer->CreateSubContext( contextInitParams );
	HELIUM_ASSERT( spSubRenderContext );
#endif

	Input::Initialize(&hMainWnd, false);

	{
		AssetPath prePassShaderPath;
		HELIUM_VERIFY( prePassShaderPath.Set(
			HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "PrePass.hlsl" ) ) );

		AssetPtr spPrePassShader;
		HELIUM_VERIFY( AssetLoader::GetStaticInstance()->LoadObject( prePassShaderPath, spPrePassShader ) );

		HELIUM_ASSERT( spPrePassShader.Get() );
	}

	RenderResourceManager& rRenderResourceManager = RenderResourceManager::GetStaticInstance();
	rRenderResourceManager.Initialize();
	rRenderResourceManager.UpdateMaxViewportSize( displayWidth, displayHeight );

	//// Create a scene definition
	SceneDefinitionPtr spSceneDefinition;
	gAssetLoader->LoadObject( AssetPath( TXT( "/ExampleGames/Empty/Scenes/TestScene:SceneDefinition" ) ), spSceneDefinition );

	EntityDefinitionPtr spEntityDefinition;
	gAssetLoader->LoadObject( AssetPath( TXT( "/ExampleGames/Empty/Scenes/TestScene:TestBull_Entity" ) ), spEntityDefinition );

	DynamicDrawer& rDynamicDrawer = DynamicDrawer::GetStaticInstance();
	HELIUM_VERIFY( rDynamicDrawer.Initialize() );

	RRenderContextPtr spMainRenderContext = pRenderer->GetMainContext();
	HELIUM_ASSERT( spMainRenderContext );
	
	WorldManager& rWorldManager = WorldManager::GetStaticInstance();
	HELIUM_VERIFY( rWorldManager.Initialize() );

	// Create a world
	WorldPtr spWorld( rWorldManager.CreateWorld( spSceneDefinition ) );
	HELIUM_ASSERT( spWorld );
	HELIUM_TRACE( TraceLevels::Info, TXT( "Created world \"%s\".\n" ), *spSceneDefinition->GetPath().ToString() );

	//Slice *pRootSlice = spWorld->GetRootSlice();
	//Entity *pEntity = pRootSlice->CreateEntity(spEntityDefinition);
			
	GraphicsScene* pGraphicsScene = spWorld->GetComponents().GetFirst<GraphicsManagerComponent>()->GetGraphicsScene();
	HELIUM_ASSERT( pGraphicsScene );
	GraphicsSceneView* pMainSceneView = NULL;
	if( pGraphicsScene )
	{
		uint32_t mainSceneViewId = pGraphicsScene->AllocateSceneView();
		if( IsValid( mainSceneViewId ) )
		{
			float32_t aspectRatio =
				static_cast< float32_t >( displayWidth ) / static_cast< float32_t >( displayHeight );

			RSurface* pDepthStencilSurface = rRenderResourceManager.GetDepthStencilSurface();
			HELIUM_ASSERT( pDepthStencilSurface );

			pMainSceneView = pGraphicsScene->GetSceneView( mainSceneViewId );
			HELIUM_ASSERT( pMainSceneView );
			pMainSceneView->SetRenderContext( spMainRenderContext );
			pMainSceneView->SetDepthStencilSurface( pDepthStencilSurface );
			pMainSceneView->SetAspectRatio( aspectRatio );
			pMainSceneView->SetViewport( 0, 0, displayWidth, displayHeight );
			pMainSceneView->SetClearColor( Color( 0x00202020 ) );

			//spMainCamera->SetSceneViewId( mainSceneViewId );

#if MULTI_WINDOW
			uint32_t subSceneViewId = pGraphicsScene->AllocateSceneView();
			if( IsValid( subSceneViewId ) )
			{
				GraphicsSceneView* pSubSceneView = pGraphicsScene->GetSceneView( subSceneViewId );
				HELIUM_ASSERT( pSubSceneView );
				pSubSceneView->SetRenderContext( spSubRenderContext );
				pSubSceneView->SetDepthStencilSurface( pDepthStencilSurface );
				pSubSceneView->SetAspectRatio( aspectRatio );
				pSubSceneView->SetViewport( 0, 0, displayWidth, displayHeight );
				pSubSceneView->SetClearColor( Color( 0x00202020 ) );

				//spSubCamera->SetSceneViewId( subSceneViewId );
			}
#endif
		}
	
#if !HELIUM_RELEASE && !HELIUM_PROFILE
		BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
		rSceneDrawer.DrawScreenText(
			20,
			20,
			String( TXT( "CACHING" ) ),
			Color( 0xff00ff00 ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );
		rSceneDrawer.DrawScreenText(
			21,
			20,
			String( TXT( "CACHING" ) ),
			Color( 0xff00ff00 ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );

		//rSceneDrawer.Draw

		//Helium::DynamicDrawer &drawer = DynamicDrawer::GetStaticInstance();
		//drawer.
#endif
	}

	rWorldManager.Update();
	
	float time = 0.0f;

#if MULTI_WINDOW
	spSubRenderContext.Release();
#endif
	spMainRenderContext.Release();

	
	Helium::StrongPtr<Helium::Texture2d> texture;
	gAssetLoader->LoadObject( AssetPath( TXT( "/Textures:Triangle.png" ) ), texture);

	Helium::RTexture2d *rTexture2d = texture->GetRenderResource2d();


	while( windowData.bProcessMessages )
	{
#if GRAPHICS_SCENE_BUFFERED_DRAWER
		BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
		rSceneDrawer.DrawScreenText(
			20,
			20,
			String( TXT( "RUNNING" ) ),
			Color( 0xffffffff ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );
		rSceneDrawer.DrawScreenText(
			21,
			20,
			String( TXT( "RUNNING" ) ),
			Color( 0xffffffff ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );

		time += 0.01f;
		DynamicArray<SimpleVertex> verticesU;

		verticesU.New( -100.0f, -100.0f, 750.0f );
		verticesU.New( 100.0f, -100.0f, 750.0f );
		verticesU.New( 100.0f, 100.0f, 750.0f );
		verticesU.New( -100.0f, 100.0f, 750.0f );
		
		rSceneDrawer.DrawLineList( verticesU.GetData(), static_cast<uint32_t>( verticesU.GetSize() ) );
		
		DynamicArray<SimpleTexturedVertex> verticesT;
		verticesT.New( Simd::Vector3( -100.0f, 100.0f, 750.0f ), Simd::Vector2( 0.0f, 0.0f ) );
		verticesT.New( Simd::Vector3( 100.0f, 100.0f, 750.0f ), Simd::Vector2( 1.0f, 0.0f ) );
		verticesT.New( Simd::Vector3( -100.0f, -100.0f, 750.0f ), Simd::Vector2( 0.0f, 1.0f ) );
		verticesT.New( Simd::Vector3( 100.0f, -100.0f, 750.0f ), Simd::Vector2( 1.0f, 1.0f ) );
		

		//rSceneDrawer.DrawTextured(
		//	RENDERER_PRIMITIVE_TYPE_TRIANGLE_STRIP,
		//	verticesT.GetData(),
		//	verticesT.GetSize(),
		//	NULL,
		//	2,
		//	rTexture2d, Helium::Color(1.0f, 1.0f, 1.0f, 1.0f), Helium::RenderResourceManager::RASTERIZER_STATE_DEFAULT, Helium::RenderResourceManager::DEPTH_STENCIL_STATE_NONE);

		//rSceneDrawer.DrawTexturedQuad(rTexture2d);

		Helium::Simd::Matrix44 transform = Helium::Simd::Matrix44::IDENTITY;
		
		Simd::Vector3 location(0.0f, 400.0f, 0.0f);
		Simd::Quat rotation(Helium::Simd::Vector3::BasisZ, time);
		Simd::Vector3 scale(1000.0f, 1000.0f, 1000.0f);
		


		transform.SetRotationTranslationScaling(rotation, location, scale);
		rSceneDrawer.DrawTexturedQuad(rTexture2d, transform, Simd::Vector2(0.0f, 0.0f), Simd::Vector2(0.5f, 0.5f));
#endif
		
		//Helium::Simd::Vector3 up = Simd::Vector3::BasisY;
		////Helium::Simd::Vector3 eye(5000.0f * sin(time), 0.0f, 5000.0f * cos(time));
		//Helium::Simd::Vector3 eye(0.0f, 0.0f, -1000.0f);
		//Helium::Simd::Vector3 forward = Simd::Vector3::Zero - eye;
		//forward.Normalize();

		////pMainSceneView->SetClearColor( Color( 0xffffffff ) );
		//pMainSceneView->SetView(eye, forward, up);




		if (Input::IsKeyDown(Input::KeyCodes::KC_A))
		{
			HELIUM_TRACE( TraceLevels::Info, TXT( "A is down" ) );
		}

		if (Input::IsKeyDown(Input::KeyCodes::KC_ESCAPE))
		{
			HELIUM_TRACE( TraceLevels::Info, TXT( "Exiting" ) );
			break;
		}

		MSG message;
		if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) )
		{
			TranslateMessage( &message );
			DispatchMessage( &message );

			if( windowData.bShutdownRendering )
			{
				if( spWorld )
				{
					spWorld->Shutdown();
				}

				spWorld.Release();
				WorldManager::DestroyStaticInstance();

				spSceneDefinition.Release();
				spEntityDefinition.Release();

				DynamicDrawer::DestroyStaticInstance();
				RenderResourceManager::DestroyStaticInstance();

				Renderer::DestroyStaticInstance();

				break;
			}

			if( message.message == WM_QUIT )
			{
				windowData.bProcessMessages = false;
				windowData.resultCode = static_cast< int >( message.wParam );
				resultCode = static_cast< int >( message.wParam );

				break;
			}
		}

		rWorldManager.Update();

#if GRAPHICS_SCENE_BUFFERED_DRAWER
		if( pGraphicsScene )
		{
			BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
			rSceneDrawer.DrawScreenText(
				20,
				20,
				String( TXT( "Debug text test!" ) ),
				Color( 0xffffffff ) );
		}
#endif
	}

	if( spWorld )
	{
		spWorld->Shutdown();
	}

	spWorld.Release();
	}
	WorldManager::DestroyStaticInstance();
	

	DynamicDrawer::DestroyStaticInstance();
	RenderResourceManager::DestroyStaticInstance();

	Helium::Input::Cleanup();

	Renderer::DestroyStaticInstance();
	

	JobManager::DestroyStaticInstance();

	Config::DestroyStaticInstance();

#if HELIUM_TOOLS
	AssetPreprocessor::DestroyStaticInstance();
#endif
	AssetLoader::DestroyStaticInstance();
	CacheManager::DestroyStaticInstance();
	
	Helium::Components::Cleanup();
	

	Reflect::Cleanup();
	AssetType::Shutdown();
	Asset::Shutdown();


	Reflect::ObjectRefCountSupport::Shutdown();
	Helium::Bullet::Cleanup();

	AssetPath::Shutdown();
	Name::Shutdown();

	FileLocations::Shutdown();

	ThreadLocalStackAllocator::ReleaseMemoryHeap();

#if HELIUM_ENABLE_MEMORY_TRACKING
	DynamicMemoryHeap::LogMemoryStats();
	ThreadLocalStackAllocator::ReleaseMemoryHeap();
#endif

	return resultCode;
}
/// Initialize all resources provided by this manager.
///
/// @see Cleanup(), PostConfigUpdate()
bool RenderResourceManager::Initialize()
{
	// Release any existing resources.
	Cleanup();

	// Get the renderer and graphics configuration.
	Renderer* pRenderer = Renderer::GetInstance();
	if ( !pRenderer )
	{
		return false;
	}

	Config* pConfig = Config::GetInstance();
	if ( !HELIUM_VERIFY( pConfig ) )
	{
		return false;
	}

	StrongPtr< GraphicsConfig > spGraphicsConfig( pConfig->GetConfigObject< GraphicsConfig >( Name( "GraphicsConfig" ) ) );
	if ( !spGraphicsConfig )
	{
		HELIUM_TRACE( TraceLevels::Error, "RenderResourceManager::Initialize(): Initialization failed; missing GraphicsConfig.\n" );
		return false;
	}

	// Create the standard rasterizer states.
	RRasterizerState::Description rasterizerStateDesc;

	rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_SOLID;
	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
	rasterizerStateDesc.winding = RENDERER_WINDING_CLOCKWISE;
	rasterizerStateDesc.depthBias = 0;
	rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
	m_rasterizerStates[RASTERIZER_STATE_DEFAULT] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DEFAULT] );

	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_NONE;
	m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] );

	rasterizerStateDesc.depthBias = 1;
	rasterizerStateDesc.slopeScaledDepthBias = 2.0f;
	m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] );

	rasterizerStateDesc.depthBias = 0;
	rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
	rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_WIREFRAME;
	m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] = pRenderer->CreateRasterizerState(
		rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] );

	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
	m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] );

	// Create the standard blend states.
	RBlendState::Description blendStateDesc;

	blendStateDesc.bBlendEnable = false;
	m_blendStates[BLEND_STATE_OPAQUE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_OPAQUE] );

	blendStateDesc.colorWriteMask = 0;
	m_blendStates[BLEND_STATE_NO_COLOR] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_NO_COLOR] );

	blendStateDesc.colorWriteMask = RENDERER_COLOR_WRITE_MASK_FLAG_ALL;
	blendStateDesc.bBlendEnable = true;

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_SRC_ALPHA;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_INV_SRC_ALPHA;
	blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
	m_blendStates[BLEND_STATE_TRANSPARENT] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_TRANSPARENT] );

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_ONE;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ONE;
	m_blendStates[BLEND_STATE_ADDITIVE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_ADDITIVE] );

	blendStateDesc.function = RENDERER_BLEND_FUNCTION_REVERSE_SUBTRACT;
	m_blendStates[BLEND_STATE_SUBTRACTIVE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_SUBTRACTIVE] );

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_DEST_COLOR;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ZERO;
	blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
	m_blendStates[BLEND_STATE_MODULATE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_MODULATE] );

	// Create the standard depth/stencil states.
	RDepthStencilState::Description depthStateDesc;

	depthStateDesc.stencilWriteMask = 0;
	depthStateDesc.bStencilTestEnable = false;

	depthStateDesc.depthFunction = RENDERER_COMPARE_FUNCTION_LESS_EQUAL;
	depthStateDesc.bDepthTestEnable = true;
	depthStateDesc.bDepthWriteEnable = true;
	m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] );

	depthStateDesc.bDepthWriteEnable = false;
	m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] );

	depthStateDesc.bDepthTestEnable = false;
	m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] );

	// Create the standard sampler states that are not dependent on configuration settings.
	RSamplerState::Description samplerStateDesc;
	samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_POINT_MAG_POINT_MIP_POINT;
	samplerStateDesc.addressModeW = RENDERER_TEXTURE_ADDRESS_MODE_CLAMP;
	samplerStateDesc.mipLodBias = 0;
	samplerStateDesc.maxAnisotropy = spGraphicsConfig->GetMaxAnisotropy();

	for ( size_t addressModeIndex = 0; addressModeIndex < RENDERER_TEXTURE_ADDRESS_MODE_MAX; ++addressModeIndex )
	{
		ERendererTextureAddressMode addressMode = static_cast<ERendererTextureAddressMode>( addressModeIndex );
		samplerStateDesc.addressModeU = addressMode;
		samplerStateDesc.addressModeV = addressMode;
		samplerStateDesc.addressModeW = addressMode;

		m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] = pRenderer->CreateSamplerState( samplerStateDesc );
		HELIUM_ASSERT( m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] );
	}

	// Create the standard set of mesh vertex descriptions.
	RVertexDescription::Element vertexElements[6];

	vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_3;
	vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
	vertexElements[0].semanticIndex = 0;
	vertexElements[0].bufferIndex = 0;

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[3].semanticIndex = 1;
	vertexElements[3].bufferIndex = 0;

	m_spSimpleVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 2 );
	HELIUM_ASSERT( m_spSimpleVertexDescription );

	m_spSimpleTexturedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
	HELIUM_ASSERT( m_spSimpleTexturedVertexDescription );

	m_spProjectedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 4 );
	HELIUM_ASSERT( m_spProjectedVertexDescription );

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[3].semanticIndex = 0;
	vertexElements[3].bufferIndex = 0;

	vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[4].semanticIndex = 0;
	vertexElements[4].bufferIndex = 0;

	vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[5].semanticIndex = 1;
	vertexElements[5].bufferIndex = 0;

	m_staticMeshVertexDescriptions[0] = pRenderer->CreateVertexDescription( vertexElements, 5 );
	HELIUM_ASSERT( m_staticMeshVertexDescriptions[0] );

	m_staticMeshVertexDescriptions[1] = pRenderer->CreateVertexDescription( vertexElements, 6 );
	HELIUM_ASSERT( m_staticMeshVertexDescriptions[1] );

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_BLENDWEIGHT;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_BLENDINDICES;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
	vertexElements[3].semanticIndex = 0;
	vertexElements[3].bufferIndex = 0;

	vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
	vertexElements[4].semanticIndex = 0;
	vertexElements[4].bufferIndex = 0;

	vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[5].semanticIndex = 0;
	vertexElements[5].bufferIndex = 0;

	m_spSkinnedMeshVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 6 );
	HELIUM_ASSERT( m_spSkinnedMeshVertexDescription );

	vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
	vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
	vertexElements[0].semanticIndex = 0;
	vertexElements[0].bufferIndex = 0;

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	m_spScreenVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
	HELIUM_ASSERT( m_spScreenVertexDescription );

	// Create configuration-dependent render resources.
	PostConfigUpdate();

	// Attempt to load the depth-only pre-pass shader.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetLoader* pAssetLoader = AssetLoader::GetInstance();
	HELIUM_ASSERT( pAssetLoader );

#ifdef HELIUM_DIRECT3D

	AssetPath prePassShaderPath;
	HELIUM_VERIFY( prePassShaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "PrePass.hlsl" ) );

	AssetPtr spPrePassShader;
	HELIUM_VERIFY( pAssetLoader->LoadObject( prePassShaderPath, spPrePassShader ) );

	Shader* pPrePassShader = Reflect::SafeCast< Shader >( spPrePassShader.Get() );
	if ( HELIUM_VERIFY( pPrePassShader ) )
	{
		size_t loadId = pPrePassShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pPrePassShader->TryFinishLoadVariant( loadId, m_spPrePassVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	// Attempt to load the simple world-space, simple screen-space, and screen-space text shaders.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetPath shaderPath;
	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "Simple.hlsl" ) );

	AssetPtr spShader;
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );

	Shader* pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpaceVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpacePixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenSpaceTexture.hlsl" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );
	pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpaceVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpacePixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenText.hlsl" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );
	pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextPixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	// Attempt to load the debug fonts.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetPath fontPath;
	AssetPtr spFont;

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugSmall" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_SMALL] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugMedium" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_MEDIUM] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugLarge" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_LARGE] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

#endif

	return true;
}
Esempio n. 20
0
/// Initialize this package loader.
///
/// @param[in] packagePath  Asset path of the package to load.
///
/// @return  True if this loader was initialized successfully, false if not.
///
/// @see Shutdown()
bool LoosePackageLoader::Initialize( AssetPath packagePath )
{
	Shutdown();

	// Make sure the path represents a package.
	if( packagePath.IsEmpty() )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "LoosePackageLoader::Initialize(): Empty package path specified.\n" ) );

		return false;
	}

	HELIUM_TRACE(
		TraceLevels::Debug,
		TXT( "LoosePackageLoader::Initialize(): Initializing loader for package \"%s\".\n" ),
		*packagePath.ToString() );

	if( !packagePath.IsPackage() )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "LoosePackageLoader::Initialize(): \"%s\" does not represent a package path.\n" ),
			*packagePath.ToString() );

		return false;
	}

	// Store the package path.
	m_packagePath = packagePath;

	// Attempt to locate the specified package if it already happens to exist.
	m_spPackage = Asset::Find< Package >( packagePath );
	Package* pPackage = m_spPackage;
	if( pPackage )
	{
		if( pPackage->GetLoader() )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "LoosePackageLoader::Initialize(): Package \"%s\" already has a loader.\n" ),
				*packagePath.ToString() );

			m_spPackage.Release();

			return false;
		}

		pPackage->SetLoader( this );
	}
	else
	{
		// Make sure we don't have a name clash with a non-package object.
		AssetPtr spObject( Asset::FindObject( packagePath ) );
		if( spObject )
		{
			HELIUM_ASSERT( !spObject->IsPackage() );

			HELIUM_TRACE(
				TraceLevels::Error,
				( TXT( "PackageLoader::Initialize(): Package loader cannot be initialized for \"%s\", as an " )
				TXT( "object with the same name exists that is not a package.\n" ) ),
				*packagePath.ToString() );

			return false;
		}
	}

	// Build the package file path.  If the package is a user configuration package, use the user data directory,
	// otherwise use the global data directory.
	Config& rConfig = Config::GetStaticInstance();
	FilePath dataDirectory;

	if ( !FileLocations::GetDataDirectory( dataDirectory ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "PackageLoader::Initialize(): Could not obtain user data directory." ) );

		return false;
	}

	// Set up to read the TOC (which may not exist)
	//SetInvalid( m_packageTocFileSize );

	// First do this check without a trailing "/" so that FilePath has to actually look at the file system
	FilePath package_dir = dataDirectory + packagePath.ToFilePathString().GetData();
	
	if (!package_dir.Exists())
	{
		// Some packages like types or uninitialized user config packages may not exist on file system
		m_packageDirPath = package_dir + TXT("/");
		return true;
	}

	if (!package_dir.IsDirectory())
	{
		// Packages should not be files
		return false;
	}
	
	// But internally we will store this 
	m_packageDirPath = package_dir + TXT("/");

	return true;
}
Esempio n. 21
0
/// Begin asynchronous pre-loading of package information.
///
/// @see TryFinishPreload()
bool LoosePackageLoader::BeginPreload()
{
	HELIUM_ASSERT( !m_startPreloadCounter );
	HELIUM_ASSERT( !m_preloadedCounter );
	HELIUM_ASSERT( IsInvalid( m_parentPackageLoadId ) );

	// Load the parent package if we need to create the current package.
	if( !m_spPackage )
	{
		AssetPath parentPackagePath = m_packagePath.GetParent();
		if( !parentPackagePath.IsEmpty() )
		{
			AssetLoader* pAssetLoader = AssetLoader::GetStaticInstance();
			HELIUM_ASSERT( pAssetLoader );

			m_parentPackageLoadId = pAssetLoader->BeginLoadObject( parentPackagePath );
			HELIUM_ASSERT( IsValid( m_parentPackageLoadId ) );
		}
	}

	AsyncLoader &rAsyncLoader = AsyncLoader::GetStaticInstance();

	if ( !m_packageDirPath.Exists() )
	{
		HELIUM_TRACE(
			TraceLevels::Warning,
			"LoosePackageLoader::BeginPreload - Package physical path '%s' does not exist\n", 
			m_packageDirPath.c_str());
	}
	else if ( !m_packageDirPath.IsDirectory() )
	{
		HELIUM_TRACE(
			TraceLevels::Warning,
			"LoosePackageLoader::BeginPreload - Package physical path '%s' is not a directory\n", 
			m_packageDirPath.c_str());
	}
	else
	{
		DirectoryIterator packageDirectory( m_packageDirPath );

		HELIUM_TRACE( TraceLevels::Info, TXT(" LoosePackageLoader::BeginPreload - Issuing read requests for all files in %s\n"), m_packageDirPath.c_str() );

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

#if HELIUM_TOOLS
			if ( item.m_Path.IsDirectory() )
			{
				AssetPath packagePath;
				std::string name = item.m_Path.DirectoryAsVector().back();
				packagePath.Set( Name( name.c_str() ), true, m_packagePath );
				m_childPackagePaths.Add( packagePath );
				HELIUM_TRACE( TraceLevels::Info, TXT("- Skipping directory [%s]\n"), item.m_Path.c_str(), item.m_Path.Extension().c_str() );
			}
			else
#endif
			if ( item.m_Path.Extension() == Persist::ArchiveExtensions[ Persist::ArchiveTypes::Json ] )
			{
				HELIUM_TRACE( TraceLevels::Info, TXT("- Reading file [%s]\n"), item.m_Path.c_str() );

				FileReadRequest *request = m_fileReadRequests.New();
				request->expectedSize = item.m_Size;

				HELIUM_ASSERT( item.m_Size < UINT32_MAX );

				// Create a buffer for the file to be read into temporarily
				request->pLoadBuffer = DefaultAllocator().Allocate( static_cast< size_t > ( item.m_Size ) + 1 );
				static_cast< char* >( request->pLoadBuffer )[ static_cast< size_t > ( item.m_Size ) ] = '\0'; // for efficiency parsing text files
				HELIUM_ASSERT( request->pLoadBuffer );

				// Queue up the read
				request->asyncLoadId = rAsyncLoader.QueueRequest( request->pLoadBuffer, String( item.m_Path.c_str() ), 0, static_cast< size_t >( item.m_Size ) );
				HELIUM_ASSERT( IsValid( request->asyncLoadId ) );

				request->filePath = item.m_Path;
				request->fileTimestamp = item.m_ModTime;
			}
			else
			{
				HELIUM_TRACE( TraceLevels::Info, TXT("- Skipping file [%s] (Extension is %s)\n"), item.m_Path.c_str(), item.m_Path.Extension().c_str() );
			}
		}
	}

	AtomicExchangeRelease( m_startPreloadCounter, 1 );

	return true;
}
Esempio n. 22
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;
}
Esempio n. 23
0
/// @copydoc ResourceHandler::CacheResource()
bool ShaderResourceHandler::CacheResource(
    AssetPreprocessor* pAssetPreprocessor,
    Resource* pResource,
    const String& rSourceFilePath )
{
    HELIUM_ASSERT( pAssetPreprocessor );
    HELIUM_ASSERT( pResource );

    const Shader* pShader = Reflect::AssertCast< const Shader >( pResource );
    AssetPath shaderPath = pShader->GetPath();

    HELIUM_TRACE( TraceLevels::Info, TXT( "ShaderResourceHandler: Caching \"%s\".\n" ), *shaderPath.ToString() );

    DefaultAllocator allocator;

    FileStream* pSourceFileStream = FileStream::OpenFileStream( rSourceFilePath, FileStream::MODE_READ );
    if( !pSourceFileStream )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "ShaderResourceHandler: Source file for shader resource \"%s\" failed to open properly.\n" ),
            *shaderPath.ToString() );

        return false;
    }

    // Load the entire shader resource into memory.
    int64_t size64 = pSourceFileStream->GetSize();
    HELIUM_ASSERT( size64 != -1 );

    HELIUM_ASSERT( static_cast< uint64_t >( size64 ) <= static_cast< size_t >( -1 ) );
    if( size64 > static_cast< uint64_t >( static_cast< size_t >( -1 ) ) )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            ( TXT( "ShaderResourceHandler: Source file for shader resource \"%s\" is too large to fit into " )
            TXT( "memory for preprocessing.\n" ) ),
            *shaderPath.ToString() );

        delete pSourceFileStream;

        return false;
    }

    size_t size = static_cast< size_t >( size64 );

    void* pShaderData = allocator.Allocate( size );
    HELIUM_ASSERT( pShaderData );
    if( !pShaderData )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            ( TXT( "ShaderResourceHandler: Failed to allocate %" ) PRIuSZ TXT( " bytes for loading the source " )
            TXT( "data of \"%s\" for preprocessing.\n" ) ),
            size,
            *shaderPath.ToString() );

        delete pSourceFileStream;

        return false;
    }

    BufferedStream( pSourceFileStream ).Read( pShaderData, 1, size );

    delete pSourceFileStream;

    // Parse all preprocessor toggle and selection tokens from the shader source.
    StrongPtr< Shader::PersistentResourceData > resourceData( new Shader::PersistentResourceData() );

    const char* pLineEnd = static_cast< const char* >( pShaderData );
    const char* pShaderEnd = pLineEnd + size;

    do
    {
        const char* pLineStart = pLineEnd;
        while( pLineEnd < pShaderEnd )
        {
            char character = *pLineEnd;
            if( character == '\n' || character == '\r' )
            {
                break;
            }

            ++pLineEnd;
        }

        ParseLine( shaderPath, *resourceData, pLineStart, pLineEnd );

        while( pLineEnd < pShaderEnd )
        {
            char character = *pLineEnd;
            if( character != '\n' && character != '\r' )
            {
                break;
            }

            ++pLineEnd;
        }
    } while( pLineEnd < pShaderEnd );

    allocator.Free( pShaderData );

    // Serialize the persistent shader resource data for each platform.
    for( size_t platformIndex = 0; platformIndex < static_cast< size_t >( Cache::PLATFORM_MAX ); ++platformIndex )
    {
        PlatformPreprocessor* pPreprocessor = pAssetPreprocessor->GetPlatformPreprocessor(
            static_cast< Cache::EPlatform >( platformIndex ) );
        if( !pPreprocessor )
        {
            continue;
        }

        Resource::PreprocessedData& rPreprocessedData = pResource->GetPreprocessedData(
            static_cast< Cache::EPlatform >( platformIndex ) );
        SaveObjectToPersistentDataBuffer(resourceData.Get(), rPreprocessedData.persistentDataBuffer);
        rPreprocessedData.subDataBuffers.Resize( 0 );
        rPreprocessedData.bLoaded = true;
    }

    

    return true;
}
Esempio n. 24
0
/// @copydoc PackageLoader::BeginLoadObject()
size_t CachePackageLoader::BeginLoadObject( AssetPath path, Reflect::ObjectResolver *pResolver, bool forceReload )
{
	HELIUM_ASSERT( m_pCache );
	HELIUM_ASSERT( !forceReload ); // Not supported

	// Don't load packages from the cache, but instead create them dynamically.
	if( path.IsPackage() )
	{
		HELIUM_TRACE(
			TraceLevels::Debug,
			"CachePackageLoader::BeginLoadObject(): \"%s\" is a package, resolving immediately.\n",
			*path.ToString() );

		LoadRequest* pRequest = m_loadRequestPool.Allocate();
		HELIUM_ASSERT( pRequest );
		pRequest->pEntry = NULL;
		pRequest->pResolver = pResolver;

		ResolvePackage( pRequest->spObject, path );
		HELIUM_ASSERT( pRequest->spObject );

		SetInvalid( pRequest->asyncLoadId );
		pRequest->pAsyncLoadBuffer = NULL;
		pRequest->pPropertyDataBegin = NULL;
		pRequest->pPropertyDataEnd = NULL;
		pRequest->pPersistentResourceDataBegin = NULL;
		pRequest->pPersistentResourceDataEnd = NULL;
		SetInvalid( pRequest->ownerLoadIndex );
		HELIUM_ASSERT( !pRequest->spOwner );
		pRequest->forceReload = forceReload;

		pRequest->flags = LOAD_FLAG_PRELOADED;

		size_t requestId = m_loadRequests.Add( pRequest );

		return requestId;
	}

	const Cache::Entry* pEntry = m_pCache->FindEntry( path, 0 );
	if( !pEntry )
	{
		HELIUM_TRACE(
			TraceLevels::Debug,
			"CachePackageLoader::BeginLoadObject(): \"%s\" is not cached in this package.  No load request added.\n",
			*path.ToString() );

		return Invalid< size_t >();
	}

#ifndef NDEBUG
	size_t loadRequestSize = m_loadRequests.GetSize();
	for( size_t loadRequestIndex = 0; loadRequestIndex < loadRequestSize; ++loadRequestIndex )
	{
		if( !m_loadRequests.IsElementValid( loadRequestIndex ) )
		{
			continue;
		}

		LoadRequest* pRequest = m_loadRequests[ loadRequestIndex ];
		HELIUM_ASSERT( pRequest );
		HELIUM_ASSERT( pRequest->pEntry != pEntry );
		if( pRequest->pEntry == pEntry )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				"CachePackageLoader::BeginLoadObject(): Duplicate load request of \"%s\".  No load request added.\n",
				*path.ToString() );

			return Invalid< size_t >();
		}
	}
#endif

	LoadRequest* pRequest = m_loadRequestPool.Allocate();
	HELIUM_ASSERT( pRequest );
	pRequest->pEntry = pEntry;
	pRequest->pResolver = pResolver;
	HELIUM_ASSERT( !pRequest->spObject );
	SetInvalid( pRequest->asyncLoadId );
	pRequest->pAsyncLoadBuffer = NULL;
	pRequest->pPropertyDataBegin = NULL;
	pRequest->pPropertyDataEnd = NULL;
	pRequest->pPersistentResourceDataBegin = NULL;
	pRequest->pPersistentResourceDataEnd = NULL;
	SetInvalid( pRequest->ownerLoadIndex );
	HELIUM_ASSERT( !pRequest->spOwner );
	pRequest->forceReload = forceReload;

	pRequest->flags = 0;

	// If a fully-loaded object already exists with the same name, do not attempt to re-load the object (just mark
	// the request as complete).
	pRequest->spObject = Asset::FindObject( pEntry->path );

	Asset* pObject = pRequest->spObject;
	if( pObject && pObject->IsFullyLoaded() )
	{
		HELIUM_TRACE(
			TraceLevels::Debug,
			"CachePackageLoader::BeginLoadObject(): \"%s\" is already fully loaded.  Bypassing load process.\n",
			*path.ToString() );

		pRequest->flags = LOAD_FLAG_PRELOADED;
	}
	else
	{
		HELIUM_ASSERT( !pObject || !pObject->GetAnyFlagSet( Asset::FLAG_LOADED | Asset::FLAG_LINKED ) );

		HELIUM_TRACE(
			TraceLevels::Debug,
			"CachePackageLoader::BeginLoadObject(): Issuing async load of property data for \"%s\".\n",
			*path.ToString() );

		size_t entrySize = pEntry->size;
		pRequest->pAsyncLoadBuffer = static_cast< uint8_t* >( DefaultAllocator().Allocate( entrySize ) );
		HELIUM_ASSERT( pRequest->pAsyncLoadBuffer );

		AsyncLoader* pAsyncLoader = AsyncLoader::GetInstance();
		HELIUM_ASSERT( pAsyncLoader );

		pRequest->asyncLoadId = pAsyncLoader->QueueRequest(
			pRequest->pAsyncLoadBuffer,
			m_pCache->GetCacheFileName(),
			pEntry->offset,
			entrySize );
		HELIUM_ASSERT( IsValid( pRequest->asyncLoadId ) );
	}

	size_t requestId = m_loadRequests.Add( pRequest );

	HELIUM_TRACE(
		TraceLevels::Debug,
		"CachePackageLoader::BeginLoadObject(): Load request for \"%s\" added (ID: %" PRIuSZ ").\n",
		*path.ToString(),
		requestId );

	return requestId;
}
Esempio n. 25
0
/// Initialize this system.
///
/// @param[in] rCommandLineInitialization    Interface for initializing command-line parameters.
/// @param[in] rMemoryHeapPreInitialization  Interface for performing any necessary pre-initialization of dynamic
///                                          memory heaps.
/// @param[in] rAssetLoaderInitialization   Interface for creating and initializing the main AssetLoader instance.
///                                          Note that this must remain valid until Shutdown() is called on this
///                                          system, as a reference to it will be held by this system.
/// @param[in] rConfigInitialization         Interface for initializing application configuration settings.
/// @param[in] rWindowManagerInitialization  Interface for creating and initializing the global window manager
///                                          instance.
/// @param[in] rRendererInitialization       Interface for creating and initializing the global renderer instance.
/// @param[in] pWorldType                    Type of World to create for the main world.  If this is null, the
///                                          actual World type will be used.
bool GameSystem::Initialize(
	CommandLineInitialization& rCommandLineInitialization,
	MemoryHeapPreInitialization& rMemoryHeapPreInitialization,
	AssetLoaderInitialization& rAssetLoaderInitialization,
	ConfigInitialization& rConfigInitialization,
	WindowManagerInitialization& rWindowManagerInitialization,
	RendererInitialization& rRendererInitialization,
	AssetPath &rSystemDefinitionPath)
{
	// Initialize the timer first of all, in case someone wants to use it.
	Timer::StaticInitialize();

	// Initialize command-line parameters.
	bool bCommandLineInitSuccess = rCommandLineInitialization.Initialize( m_moduleName, m_arguments );
	HELIUM_ASSERT( bCommandLineInitSuccess );
	if( !bCommandLineInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Command-line initialization failed.\n" ) );

		return false;
	}

#if HELIUM_ENABLE_TRACE
	HELIUM_TRACE( TraceLevels::Info, TXT( "Module name: %s\n" ), *m_moduleName );
	HELIUM_TRACE( TraceLevels::Info, TXT( "Command-line arguments:\n" ) );
	size_t argumentCount = m_arguments.GetSize();
	for( size_t argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex )
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "* %s\n" ), *m_arguments[ argumentIndex ] );
	}
#endif


	// Initialize the async loading thread.
	bool bAsyncLoaderInitSuccess = AsyncLoader::GetStaticInstance().Initialize();
	HELIUM_ASSERT( bAsyncLoaderInitSuccess );
	if( !bAsyncLoaderInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Async loader initialization failed.\n" ) );

		return false;
	}

	//pmd - Initialize the cache manager
	FilePath baseDirectory;
	if ( !FileLocations::GetBaseDirectory( baseDirectory ) )
	{
	  HELIUM_TRACE( TraceLevels::Error, TXT( "Could not get base directory." ) );
	  return false;
	}

	HELIUM_VERIFY( CacheManager::InitializeStaticInstance( baseDirectory ) );

	// Initialize the reflection type registry and register Asset-based types.
	Reflect::Initialize();
	
	Components::Initialize();
	
	TaskScheduler::CalculateSchedule();

	// Perform dynamic memory heap pre-initialization.
	rMemoryHeapPreInitialization.PreInitialize();

	// Create and initialize the main AssetLoader instance.
	AssetLoader* pAssetLoader = rAssetLoaderInitialization.Initialize();
	HELIUM_ASSERT( pAssetLoader );
	if( !pAssetLoader )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Asset loader initialization failed.\n" ) );

		return false;
	}

	m_pAssetLoaderInitialization = &rAssetLoaderInitialization;

	// Initialize system configuration.
	bool bConfigInitSuccess = rConfigInitialization.Initialize();
	HELIUM_ASSERT( bConfigInitSuccess );
	if( !bConfigInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Failed to initialize configuration settings.\n" ) );

		return false;
	}

	if ( !rSystemDefinitionPath.IsEmpty() )
	{
		pAssetLoader->LoadObject<SystemDefinition>( rSystemDefinitionPath, m_spSystemDefinition );
		if ( !m_spSystemDefinition )
		{
			HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Could not find SystemDefinition. LoadObject on '%s' failed.\n" ), *rSystemDefinitionPath.ToString() );
		}
		else
		{
			m_spSystemDefinition->Initialize();
		}
	}

	// Initialize the job manager.
	bool bJobManagerInitSuccess = JobManager::GetStaticInstance().Initialize();
	HELIUM_ASSERT( bJobManagerInitSuccess );
	if( !bJobManagerInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Job manager initialization failed.\n" ) );

		return false;
	}

	// Create and initialize the window manager (note that we need a window manager for message loop processing, so
	// the instance cannot be left null).
	bool bWindowManagerInitSuccess = rWindowManagerInitialization.Initialize();
	HELIUM_ASSERT( bWindowManagerInitSuccess );
	if( !bWindowManagerInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Window manager initialization failed.\n" ) );

		return false;
	}
	
	// Create and initialize the renderer.
	bool bRendererInitSuccess = rRendererInitialization.Initialize();
	HELIUM_ASSERT( bRendererInitSuccess );
	if( !bRendererInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "GameSystem::Initialize(): Renderer initialization failed.\n" ) );

		return false;
	}

	m_pRendererInitialization = &rRendererInitialization;
	
	// Initialize the world manager and main game world.
	WorldManager& rWorldManager = WorldManager::GetStaticInstance();
	bool bWorldManagerInitSuccess = rWorldManager.Initialize();
	HELIUM_ASSERT( bWorldManagerInitSuccess );
	if( !bWorldManagerInitSuccess )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "World manager initialization failed.\n" ) );

		return false;
	}

	// Initialization complete.
	return true;
}
Esempio n. 26
0
SetMappingRequest::SetMappingRequest(const AssetPath& path, const AssetHash& hash) :
    _path(path.trimmed()),
    _hash(hash)
{

};
Esempio n. 27
0
RenameMappingRequest::RenameMappingRequest(const AssetPath& oldPath, const AssetPath& newPath) :
    _oldPath(oldPath.trimmed()),
    _newPath(newPath.trimmed())
{

}
Esempio n. 28
0
/// @copydoc PackageLoader::BeginLoadObject()
size_t LoosePackageLoader::BeginLoadObject( AssetPath path, Reflect::ObjectResolver *pResolver, bool forceReload )
{	
	HELIUM_TRACE( TraceLevels::Info, TXT(" LoosePackageLoader::BeginLoadObject - Loading path %s\n"), *path.ToString() );

	HELIUM_TRACE(
		TraceLevels::Debug,
		TXT( "LoosePackageLoader::BeginLoadObject: Beginning load for path \"%s\".\n"),
		*path.ToString());

	
	HELIUM_TRACE(
		TraceLevels::Debug,
		TXT( "LoosePackageLoader::BeginLoadObject: Beginning load for path \"%s\". pResolver = %x\n"),
		*path.ToString(),
		pResolver);

	// Make sure preloading has completed.
	HELIUM_ASSERT( m_preloadedCounter != 0 );
	if( !m_preloadedCounter )
	{
		return Invalid< size_t >();
	}

	// If this package is requested, simply provide the (already loaded) package instance.
	if( path == m_packagePath )
	{
		LoadRequest* pRequest = m_loadRequestPool.Allocate();
		HELIUM_ASSERT( pRequest );

		HELIUM_ASSERT( m_spPackage );
		pRequest->spObject = m_spPackage.Ptr();

		SetInvalid( pRequest->index );
		HELIUM_ASSERT( !pRequest->spType );
		HELIUM_ASSERT( !pRequest->spTemplate );
		HELIUM_ASSERT( !pRequest->spOwner );
		SetInvalid( pRequest->templateLoadId );
		SetInvalid( pRequest->ownerLoadId );
		SetInvalid( pRequest->persistentResourceDataLoadId );
		pRequest->pCachedObjectDataBuffer = NULL;
		pRequest->cachedObjectDataBufferSize = 0;
		SetInvalid( pRequest->asyncFileLoadId );
		pRequest->pAsyncFileLoadBuffer = NULL;
		pRequest->asyncFileLoadBufferSize = 0;
		pRequest->pResolver = NULL;
		pRequest->forceReload = forceReload;

		pRequest->flags = LOAD_FLAG_PRELOADED;

		size_t requestId = m_loadRequests.Add( pRequest );

		return requestId;
	}

	size_t objectIndex = FindObjectByPath( path );
	size_t objectCount = GetObjectCount();

	if( objectIndex >= objectCount )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "LoosePackageLoader::BeginLoadObject(): Failed to locate \"%s\" for loading. Verify the file exists.\n" ),
			*path.ToString() );

		return Invalid< size_t >();
	}

	SerializedObjectData& rObjectData = m_objects[ objectIndex ];

	// Verify that the metadata was read successfully
	if( !rObjectData.bMetadataGood )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "LoosePackageLoader::BeginLoadObject(): Failed to read metadata for object \"%s\" during PackagePreload. Search log for parsing errors.\n" ),
			*path.ToString() );

		return Invalid< size_t >();
	}

	// Locate the type object.
	HELIUM_ASSERT( !rObjectData.typeName.IsEmpty() );
	AssetType* pType = AssetType::Find( rObjectData.typeName );
	if( !pType )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "LoosePackageLoader::BeginLoadObject(): Failed to locate type \"%s\" for loading object \"%s\".\n" ),
			*rObjectData.typeName,
			*path.ToString() );

		HELIUM_TRACE(
			TraceLevels::Info,
			TXT( "Current registered types:\n" ) );

		for ( AssetType::ConstIterator iter = AssetType::GetTypeBegin();
			iter != AssetType::GetTypeEnd(); ++iter)
		{
			HELIUM_TRACE(
				TraceLevels::Info,
				TXT( " - %s\n" ),
				*iter->GetName() );
		}

		return Invalid< size_t >();
	}

#ifndef NDEBUG
	size_t loadRequestSize = m_loadRequests.GetSize();
	for( size_t loadRequestIndex = 0; loadRequestIndex < loadRequestSize; ++loadRequestIndex )
	{
		if( !m_loadRequests.IsElementValid( loadRequestIndex ) )
		{
			continue;
		}

		LoadRequest* pRequest = m_loadRequests[ loadRequestIndex ];
		HELIUM_ASSERT( pRequest );
		HELIUM_ASSERT( pRequest->index != objectIndex );
		if( pRequest->index == objectIndex )
		{
			return Invalid< size_t >();
		}
	}
#endif

	LoadRequest* pRequest = m_loadRequestPool.Allocate();
	HELIUM_ASSERT( pRequest );
	HELIUM_ASSERT( !pRequest->spObject );
	pRequest->index = objectIndex;
	pRequest->spType = pType;
	HELIUM_ASSERT( !pRequest->spTemplate );
	HELIUM_ASSERT( !pRequest->spOwner );
	SetInvalid( pRequest->templateLoadId );
	SetInvalid( pRequest->ownerLoadId );
	SetInvalid( pRequest->persistentResourceDataLoadId );
	pRequest->pCachedObjectDataBuffer = NULL;
	pRequest->cachedObjectDataBufferSize = 0;
	SetInvalid( pRequest->asyncFileLoadId );
	pRequest->pAsyncFileLoadBuffer = NULL;
	pRequest->asyncFileLoadBufferSize = 0;
	pRequest->pResolver = pResolver;
	pRequest->forceReload = forceReload;

	pRequest->flags = 0;

	// If a fully-loaded object already exists with the same name, do not attempt to re-load the object (just mark
	// the request as complete).

	if ( !forceReload )
	{
		pRequest->spObject = Asset::FindObject( path );
	}
	
	Asset* pObject = pRequest->spObject;
	if( pObject && pObject->IsFullyLoaded() )
	{
		pRequest->flags = LOAD_FLAG_PRELOADED;
	}
	else
	{
		HELIUM_ASSERT( !pObject || !pObject->GetAnyFlagSet( Asset::FLAG_LOADED | Asset::FLAG_LINKED ) );

		// Begin loading the template and owner objects.  Note that there isn't much reason to check for failure
		// until we tick this request, as we need to make sure any other load requests for the template/owner that
		// did succeed are properly synced anyway.
		AssetLoader* pAssetLoader = AssetLoader::GetStaticInstance();
		HELIUM_ASSERT( pAssetLoader );

		if( rObjectData.templatePath.IsEmpty() )
		{
			// Make sure the template is fully loaded.
			Asset* pTemplate = pType->GetTemplate();
			rObjectData.templatePath = pTemplate->GetPath();
			if( pTemplate->IsFullyLoaded() )
			{
				pRequest->spTemplate = pTemplate;
			}
			else
			{
				pRequest->templateLoadId = pAssetLoader->BeginLoadObject( rObjectData.templatePath );
			}
		}
		else
		{
			pRequest->templateLoadId = pAssetLoader->BeginLoadObject( rObjectData.templatePath );
		}

		AssetPath ownerPath = path.GetParent();
		if( ownerPath == m_packagePath )
		{
			// Easy check: if the owner is this package (which is likely), we don't need to load it.
			pRequest->spOwner = m_spPackage.Ptr();
		}
		else if( !ownerPath.IsEmpty() )
		{
			pRequest->ownerLoadId = pAssetLoader->BeginLoadObject( ownerPath );
		}
	}

	size_t requestId = m_loadRequests.Add( pRequest );

	return requestId;
}
Esempio n. 29
0
/// Parse the given shader source line for toggle and select options.
///
/// @param[in] shaderPath     Asset path of the shader resource being preprocessed (used for logging purposes
///                           only).
/// @param[in] rResourceData  Persistent shader resource data to update.
/// @param[in] pLineStart     Pointer to the first character in the line.
/// @param[in] pLineEnd       Pointer to the character just past the end of the line.
void ShaderResourceHandler::ParseLine(
                                      AssetPath shaderPath,
                                      Shader::PersistentResourceData& rResourceData,
                                      const char* pLineStart,
                                      const char* pLineEnd )
{
    HELIUM_UNREF( shaderPath );  // Not used if logging is disabled.

    HELIUM_ASSERT( pLineStart );
    HELIUM_ASSERT( pLineEnd >= pLineStart );

    const char linePrefix[] = "//!";
    const char toggleUserCommand[] = "@toggle";
    const char selectUserCommand[] = "@select";
    const char toggleSystemCommand[] = "@systoggle";
    const char selectSystemCommand[] = "@sysselect";

    size_t characterCount = static_cast< size_t >( pLineEnd - pLineStart );

    // Only process lines that start with the special comment prefix.
    if( characterCount < HELIUM_ARRAY_COUNT( linePrefix ) - 1 ||
        CompareString( pLineStart, linePrefix, HELIUM_ARRAY_COUNT( linePrefix ) - 1 ) != 0 )
    {
        return;
    }

    pLineStart += HELIUM_ARRAY_COUNT( linePrefix ) - 1;
    characterCount -= HELIUM_ARRAY_COUNT( linePrefix ) - 1;

    // Split the line based on groups of whitespaces.
    CharString line( pLineStart, characterCount );

    DynamicArray< CharString > splitLine;
    line.Split( splitLine, " \t\v\f", Invalid< size_t >(), true );

    // Ignore the first split if it's empty (will occur if the command is preceded by whitespaces).
    size_t splitCount = splitLine.GetSize();
    if( splitCount > 0 && splitLine[ 0 ].IsEmpty() )
    {
        splitLine.Remove( 0 );
        --splitCount;
    }

    // We need at least 2 splits (command and at least one command parameter).
    if( splitCount < 2 )
    {
        return;
    }

    // Process the command.
    DynamicArray< CharString > splitCommand;
    splitLine[ 0 ].Split( splitCommand, '_' );
    size_t commandSplitCount = splitCommand.GetSize();
    if( commandSplitCount < 1 || commandSplitCount > 2 )
    {
        // Invalid command format.
        return;
    }

    const CharString& rCommand = splitCommand[ 0 ];

    bool bToggleUserCommand = ( rCommand == toggleUserCommand );
    bool bSelectUserCommand = ( !bToggleUserCommand && rCommand == selectUserCommand );
    bool bToggleSystemCommand = ( !( bToggleUserCommand | bSelectUserCommand ) && rCommand == toggleSystemCommand );
    bool bSelectSystemCommand =
        ( !( bToggleUserCommand | bSelectUserCommand | bToggleSystemCommand ) && rCommand == selectSystemCommand );
    if( !( bToggleUserCommand | bSelectUserCommand | bToggleSystemCommand | bSelectSystemCommand ) )
    {
        return;
    }

    /// Make sure the option name (first parameter after the command name) is valid.
    String convertedString;
    HELIUM_VERIFY( ( StringConverter< char, char >::Convert( convertedString, splitLine[ 1 ] ) ) );
    Name optionName( convertedString );
    if( optionName.IsEmpty() )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "ShaderResourceHandler: Skipping empty option in shader resource \"%s\".\n" ),
            *shaderPath.ToString() );

        return;
    }

    // Make sure an existing toggle or selection option exists with the parsed option name.
    Shader::Options& rSystemOptions = rResourceData.GetSystemOptions();
    Shader::Options& rUserOptions = rResourceData.GetUserOptions();

    DynamicArray< Shader::Toggle >& rSystemToggles = rSystemOptions.GetToggles();
    DynamicArray< Shader::Select >& rSystemSelects = rSystemOptions.GetSelects();

    DynamicArray< Shader::Toggle >& rUserToggles = rUserOptions.GetToggles();
    DynamicArray< Shader::Select >& rUserSelects = rUserOptions.GetSelects();

    if( ParseLineDuplicateOptionCheck( optionName, rSystemToggles ) ||
        ParseLineDuplicateOptionCheck( optionName, rSystemSelects ) ||
        ParseLineDuplicateOptionCheck( optionName, rUserToggles ) ||
        ParseLineDuplicateOptionCheck( optionName, rUserSelects ) )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            ( TXT( "ShaderResourceHandler: Duplicate option name \"%s\" found in shader resource \"%s\".  Only " )
            TXT( "the first option will be used.\n" ) ),
            *optionName,
            *shaderPath.ToString() );

        return;
    }

    // Handle shader-specific command flags (option applies to all shader types if no flags are specified).
    uint32_t shaderFlags = ( 1 << RShader::TYPE_MAX ) - 1;
    if( commandSplitCount > 1 )
    {
        shaderFlags = 0;

        const CharString& rShaderFlags = splitCommand[ 1 ];
        size_t shaderFlagCount = rShaderFlags.GetSize();
        for( size_t flagIndex = 0; flagIndex < shaderFlagCount; ++flagIndex )
        {
            char flagCharacter = rShaderFlags[ flagIndex ];
            if( flagCharacter == 'v' )
            {
                shaderFlags |= ( 1 << RShader::TYPE_VERTEX );
            }
            else if( flagCharacter == 'p' )
            {
                shaderFlags |= ( 1 << RShader::TYPE_PIXEL );
            }
        }
    }

    // Parse the command parameters.
    if( bToggleUserCommand | bToggleSystemCommand )
    {
        Shader::Toggle* pToggle = ( bToggleUserCommand ? rUserToggles : rSystemToggles ).New();
        HELIUM_ASSERT( pToggle );
        pToggle->name = optionName;
        pToggle->shaderTypeFlags = shaderFlags;

        if( splitCount > 2 )
        {
            HELIUM_TRACE(
                TraceLevels::Warning,
                ( TXT( "ShaderResourceHandler: Extra tokens for toggle command \"%s\" in shader resource \"%s\" " )
                TXT( "ignored.\n" ) ),
                *splitLine[ 1 ],
                *shaderPath.ToString() );
        }
    }
    else
    {
        if( splitCount < 3 || ( splitCount < 4 && splitLine[ 2 ] == "NONE" ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                ( TXT( "ShaderResourceHandler: Missing options for select command \"%s\" in shader resource " )
                TXT( "\"%s\".\n" ) ),
                *splitLine[ 1 ],
                *shaderPath.ToString() );

            return;
        }

        Shader::Select* pSelect = ( bSelectUserCommand ? rUserSelects : rSystemSelects ).New();
        HELIUM_ASSERT( pSelect );
        pSelect->name = optionName;

        pSelect->shaderTypeFlags = shaderFlags;
        pSelect->bOptional = ( splitLine[ 2 ] == "NONE" );

        size_t choiceIndex = ( pSelect->bOptional ? 3 : 2 );
        for( ; choiceIndex < splitCount; ++choiceIndex )
        {
            HELIUM_VERIFY( ( StringConverter< char, char >::Convert( convertedString, splitLine[ choiceIndex ] ) ) );
            pSelect->choices.New( convertedString );
        }
    }
}
Esempio n. 30
0
GetMappingRequest::GetMappingRequest(const AssetPath& path) : _path(path.trimmed()) {
};