Esempio n. 1
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. 2
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. 3
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. 4
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. 5
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. 6
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. 7
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;
}
Esempio n. 8
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;
}
/// 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. 10
0
/// Finalize the TOC loading process.
///
/// Note that this does not free any resources on a failed load (the caller is responsible for such clean-up work).
///
/// @return  True if the TOC load was successful, false if not.
bool Cache::FinalizeTocLoad()
{
	HELIUM_ASSERT( m_pTocBuffer );

	const uint8_t* pTocCurrent = m_pTocBuffer;
	const uint8_t* pTocMax = pTocCurrent + m_tocSize;

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

	// Validate the TOC header.
	uint32_t magic;
	if( !CheckedTocRead( MemoryCopy, magic, TXT( "the header magic" ), pTocCurrent, pTocMax ) )
	{
		return false;
	}

	LOAD_VALUE_CALLBACK* pLoadFunction = NULL;
	if( magic == TOC_MAGIC )
	{
		HELIUM_TRACE(
			TraceLevels::Info,
			TXT( "Cache::FinalizeTocLoad(): TOC \"%s\" identified (no byte swapping).\n" ),
			*m_tocFileName );

		pLoadFunction = MemoryCopy;
	}
	else if( magic == TOC_MAGIC_SWAPPED )
	{
		HELIUM_TRACE(
			TraceLevels::Info,
			TXT( "Cache::FinalizeTocLoad(): TOC \"%s\" identified (byte swapping is necessary).\n" ),
			*m_tocFileName );
		HELIUM_TRACE(
			TraceLevels::Warning,
			( TXT( "Cache::TryFinishLoadToc(): Cache for TOC \"%s\" uses byte swapping, which may incur " )
			TXT( "performance penalties.\n" ) ),
			*m_tocFileName );

		pLoadFunction = ReverseByteOrder;
	}
	else
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "Cache::FinalizeTocLoad(): TOC \"%s\" has invalid file magic.\n" ),
			*m_tocFileName );

		return false;
	}

	uint32_t version;
	if( !CheckedTocRead( pLoadFunction, version, TXT( "the cache version number" ), pTocCurrent, pTocMax ) )
	{
		return false;
	}

	if( version > sm_Version )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			( TXT( "Cache::FinalizeTocLoad(): Cache version number (%" ) PRIu32 TXT( ") exceeds the maximum " )
			TXT( "supported version (%" ) PRIu32 TXT( ").\n" ) ),
			version,
			sm_Version );

		return false;
	}

	// Read the numbers of entries in the cache.
	uint32_t entryCount;
	bool bReadResult = CheckedTocRead(
		pLoadFunction,
		entryCount,
		TXT( "the number of entries in the cache" ),
		pTocCurrent,
		pTocMax );
	if( !bReadResult )
	{
		return false;
	}

	// Load the entry information.
	EntryKey key;

	uint_fast32_t entryCountFast = entryCount;
	m_entries.Reserve( entryCountFast );
	for( uint_fast32_t entryIndex = 0; entryIndex < entryCountFast; ++entryIndex )
	{
		uint16_t entryPathSize;
		bReadResult = CheckedTocRead(
			pLoadFunction,
			entryPathSize,
			TXT( "entry AssetPath string size" ),
			pTocCurrent,
			pTocMax );
		if( !bReadResult )
		{
			return false;
		}

		uint_fast16_t entryPathSizeFast = entryPathSize;

		StackMemoryHeap<>::Marker stackMarker( rStackHeap );
		char* pPathString = static_cast< char* >( rStackHeap.Allocate(
			sizeof( char ) * ( entryPathSizeFast + 1 ) ) );
		HELIUM_ASSERT( pPathString );
		pPathString[ entryPathSizeFast ] = TXT( '\0' );

		for( uint_fast16_t characterIndex = 0; characterIndex < entryPathSizeFast; ++characterIndex )
		{
			bReadResult = CheckedTocRead(
				pLoadFunction,
				pPathString[ characterIndex ],
				TXT( "entry AssetPath string character" ),
				pTocCurrent,
				pTocMax );
			if( !bReadResult )
			{
				return false;
			}
		}

		AssetPath entryPath;
		if( !entryPath.Set( pPathString ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "Cache::FinalizeTocLoad(): Failed to set AssetPath for entry %" ) PRIuFAST16 TXT( ".\n" ),
				entryIndex );

			return false;
		}

		uint32_t entrySubDataIndex;
		bReadResult = CheckedTocRead(
			pLoadFunction,
			entrySubDataIndex,
			TXT( "entry sub-data index" ),
			pTocCurrent,
			pTocMax );
		if( !bReadResult )
		{
			return false;
		}

		key.path = entryPath;
		key.subDataIndex = entrySubDataIndex;

		EntryMapType::ConstAccessor entryAccessor;
		if( m_entryMap.Find( entryAccessor, key ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				( TXT( "Cache::FinalizeTocLoad(): Duplicate entry found for AssetPath \"%s\", sub-data %" ) PRIu32
				TXT( ".\n" ) ),
				pPathString,
				entrySubDataIndex );

			return false;
		}

		uint64_t entryOffset;
		if( !CheckedTocRead( pLoadFunction, entryOffset, TXT( "entry offset" ), pTocCurrent, pTocMax ) )
		{
			return false;
		}

		int64_t entryTimestamp;
		if( !CheckedTocRead( pLoadFunction, entryTimestamp, TXT( "entry timestamp" ), pTocCurrent, pTocMax ) )
		{
			return false;
		}

		uint32_t entrySize;
		if( !CheckedTocRead( pLoadFunction, entrySize, TXT( "entry size" ), pTocCurrent, pTocMax ) )
		{
			return false;
		}

		Entry* pEntry = m_pEntryPool->Allocate();
		HELIUM_ASSERT( pEntry );
		pEntry->path = entryPath;
		pEntry->subDataIndex = entrySubDataIndex;
		pEntry->offset = entryOffset;
		pEntry->timestamp = entryTimestamp;
		pEntry->size = entrySize;

		m_entries.Add( pEntry );

		HELIUM_VERIFY( m_entryMap.Insert( entryAccessor, KeyValue< EntryKey, Entry* >( key, pEntry ) ) );
	}

	return true;
}