static duk_ret_t IAssetTransfer_Asset(duk_context* ctx)
{
    IAssetTransfer* thisObj = GetThisWeakObject<IAssetTransfer>(ctx);
    AssetPtr ret = thisObj->Asset();
    PushWeakObject(ctx, ret.Get());
    return 1;
}
Ejemplo n.º 2
0
static duk_ret_t IAsset_Clone_String(duk_context* ctx)
{
    IAsset* thisObj = GetThisWeakObject<IAsset>(ctx);
    String newAssetName = duk_require_string(ctx, 0);
    AssetPtr ret = thisObj->Clone(newAssetName);
    PushWeakObject(ctx, ret.Get());
    return 1;
}
Ejemplo n.º 3
0
/// Test whether an object load request has completed, getting the result object if so.
///
/// Note that after a load request has completed (this function returns true), the request ID should no longer be
/// considered valid.
///
/// @param[in]  id         Load request ID.
/// @param[out] rspObject  Smart pointer set to the loaded object if loading has completed.  Note that this will be
///                        set to the object instance even if the object isn't finished loading (i.e. still being
///                        linked, etc.).
///
/// @return  True if the load request has completed, false if it is still being processed.
///
/// @see FinishLoad(), BeginLoadObject()
bool AssetLoader::TryFinishLoad( size_t id, AssetPtr& rspObject )
{
	HELIUM_ASSERT( IsValid( id ) );

	// Retrieve the load request and test whether it has completed.
	LoadRequest* pRequest = m_loadRequestPool.GetObject( id );
	HELIUM_ASSERT( pRequest );

	if( ( pRequest->stateFlags & LOAD_FLAG_FULLY_LOADED ) != LOAD_FLAG_FULLY_LOADED )
	{
		return false;
	}

	HELIUM_TRACE(
		TraceLevels::Debug,
		"AssetLoader::TryFinishLoad - Completed load for asset %s\n",
		*pRequest->path.ToString());

	HELIUM_ASSERT(  !pRequest->spObject.Get() || pRequest->spObject->IsFullyLoaded() || ( pRequest->spObject->GetFlags() & Asset::FLAG_BROKEN ) );

	rspObject = pRequest->spObject;

	// Acquire an exclusive lock to the request entry.
	AssetPath objectPath = pRequest->path;

	ConcurrentHashMap< AssetPath, LoadRequest* >::Accessor requestAccessor;
	HELIUM_VERIFY( m_loadRequestMap.Find( requestAccessor, objectPath ) );
	HELIUM_ASSERT( requestAccessor->Second() == pRequest );


	// Decrement the reference count on the load request, releasing it if the reference count reaches zero.
	int32_t newRequestCount = AtomicDecrementRelease( pRequest->requestCount );
	if( newRequestCount == 0 )
	{
		pRequest->spObject.Release();
		pRequest->resolver.Clear();

		m_loadRequestMap.Remove( requestAccessor );
		m_loadRequestPool.Release( pRequest );
	}

	requestAccessor.Release();

#if HELIUM_TOOLS
	if (rspObject)
	{
		if ( !(rspObject->SetFlags(Asset::FLAG_LOAD_EVENT_FIRED) & Asset::FLAG_LOAD_EVENT_FIRED) )
		{
			AssetTracker::GetStaticInstance()->NotifyAssetLoaded( rspObject.Get() );
		}
	}
#endif

	return true;
}
Ejemplo n.º 4
0
 void OnSignal(AssetPtr param0)
 {
     duk_context* ctx = ctx_;
     duk_push_global_object(ctx);
     duk_get_prop_string(ctx, -1, "_OnSignal");
     duk_remove(ctx, -2);
     duk_push_number(ctx, (size_t)key_);
     duk_push_array(ctx);
     PushWeakObject(ctx, param0.Get());
     duk_put_prop_index(ctx, -2, 0);
     bool success = duk_pcall(ctx, 2) == 0;
     if (!success) LogError("[JavaScript] OnSignal: " + GetErrorString(ctx));
     duk_pop(ctx);
 }
Ejemplo 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 );
    }
}
Ejemplo n.º 6
0
void AssetRefListener::OnAssetCreated(AssetPtr assetData)
{
    if (assetData.Get() && !currentWaitingRef.Empty() && currentWaitingRef == assetData->Name())
    {
        /// @todo Remove this logic once a EC_Material + EC_Mesh behaves correctly without failed requests, see generated:// logic in HandleAssetRefChange.
        /** Log the same message as before for non generated:// refs. This is good to do
            because AssetAPI has now said the request failed, so user might be confused when it still works. */
        if (!currentWaitingRef.ToLower().StartsWith("generated://"))
            LogInfo("AssetRefListener: Asset \"" + assetData->Name() + "\" was created, applying after it loads.");

        // The asset we are waiting for has been created, hook to the IAsset::Loaded signal.
        currentWaitingRef = "";
        asset = assetData;
        assetData->Loaded.Connect(this, &AssetRefListener::OnAssetLoaded);
        if (myAssetAPI)
            myAssetAPI->AssetCreated.Disconnect(this, &AssetRefListener::OnAssetCreated);
    }
}
Ejemplo n.º 7
0
void RigidBody::OnCollisionMeshAssetLoaded(AssetPtr asset)
{
    IMeshAsset* meshAsset = dynamic_cast<IMeshAsset*>(asset.Get());
    if (!meshAsset)
        LogError("RigidBody::OnCollisionMeshAssetLoaded: Mesh asset load finished for asset \"" +
            asset->Name() + "\", but asset pointer was null!");

    if (shapeType.Get() == TriMesh)
    {
        impl->triangleMesh = impl->owner->GetTriangleMeshFromMeshAsset(meshAsset);
        CreateCollisionShape();
    }
    else if (shapeType.Get() == ConvexHull)
    {
        impl->convexHullSet = impl->owner->GetConvexHullSetFromMeshAsset(meshAsset);
        CreateCollisionShape();
    }

    impl->cachedShapeType = shapeType.Get();
    impl->cachedSize = size.Get();
}
Ejemplo n.º 8
0
void Sky::OnMaterialAssetLoaded(AssetPtr asset)
{
    IMaterialAsset* mAsset = dynamic_cast<IMaterialAsset*>(asset.Get());

    if (mAsset)
    {
        material_.Reset();
        material_ = Urho3D::DynamicCast<IMaterialAsset>(asset);

        if (mAsset->textures_.Size() >= 6)
        {
            AssetReferenceList list;
            for (int i=0 ; i<6 ; ++i)
                list.Append(mAsset->textures_[i].second_);

            textureRefs.Set(list, AttributeChange::LocalOnly);
            // Update call is implicit via OnTextureAssetLoaded()
        }
        else
            Update();
    }
}
Ejemplo n.º 9
0
void AssetRefListener::HandleAssetRefChange(AssetAPI *assetApi, String assetRef, const String& assetType)
{
    // Disconnect from any previous transfer we might be listening to
    if (!currentTransfer.Expired())
    {
        IAssetTransfer* current = currentTransfer.Get();
        current->Succeeded.Disconnect(this, &AssetRefListener::OnTransferSucceeded);
        current->Failed.Disconnect(this, &AssetRefListener::OnTransferFailed);
        currentTransfer.Reset();
    }
    
    assert(assetApi);

    // Store AssetAPI ptr for later signal hooking.
    if (!myAssetAPI)
        myAssetAPI = assetApi;

    // If the ref is empty, don't go any further as it will just trigger the LogWarning below.
    assetRef = assetRef.Trimmed();
    if (assetRef.Empty())
    {
        asset = AssetPtr();
        return;
    }
    currentWaitingRef = "";

    // Resolve the protocol for generated:// assets. These assets are never meant to be
    // requested from AssetAPI, they cannot be fetched from anywhere. They can only be either
    // loaded or we must wait for something to load/create them.
    String protocolPart = "";
    assetApi->ParseAssetRef(assetRef, &protocolPart);
    if (protocolPart.ToLower() == "generated")
    {
        AssetPtr loadedAsset = assetApi->FindAsset(assetRef);
        if (loadedAsset.Get() && loadedAsset->IsLoaded())
        {
            // Asset is loaded, emit Loaded with 1 msec delay to preserve the logic
            // that HandleAssetRefChange won't emit anything itself as before.
            // Otherwise existing connection can break/be too late after calling this function.
            asset = loadedAsset;
            assetApi->GetFramework()->Frame()->DelayedExecute(0.0f).Connect(this, &AssetRefListener::EmitLoaded);
            return;
        }
        else
        {
            // Wait for it to be created.
            currentWaitingRef = assetRef;
            myAssetAPI->AssetCreated.Connect(this, &AssetRefListener::OnAssetCreated);
        }
    }
    else
    {
        // This is not a generated asset, request normally from asset api.
        AssetTransferPtr transfer = assetApi->RequestAsset(assetRef, assetType);
        if (!transfer)
        {
            LogWarning("AssetRefListener::HandleAssetRefChange: Asset request for asset \"" + assetRef + "\" failed.");
            return;
        }
        currentWaitingRef = assetRef;

        transfer->Succeeded.Connect(this, &AssetRefListener::OnTransferSucceeded);
        transfer->Failed.Connect(this, &AssetRefListener::OnTransferFailed);

        currentTransfer = transfer;
    }
    
    // Disconnect from the old asset's load signal
    if (asset)
        asset->Loaded.Disconnect(this, &AssetRefListener::OnAssetLoaded);
    asset = AssetPtr();
}
Ejemplo n.º 10
0
void AssetRefListener::EmitLoaded(float /*time*/)
{
    AssetPtr currentAsset = asset.Lock();
    if (currentAsset.Get())
        Loaded.Emit(currentAsset);
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
/// 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;
}
Ejemplo n.º 13
0
/// Modify the name, owner, or instance index of this object.
///
/// @param[in] rParameters  Object rename parameters.
///
/// @return  True if this object was renamed successfully, false if not.
///
/// @see GetName(), GetOwner(), GetInstanceIndex()
bool Asset::Rename( const RenameParameters& rParameters )
{
	Name name = rParameters.name;
	Asset* pOwner = rParameters.spOwner;
	uint32_t instanceIndex = rParameters.instanceIndex;

	HELIUM_TRACE(
		TraceLevels::Debug,
		TXT("Asset::Rename(): Renaming object \"%s\" to \"%s\" (Old Owner: \"%s\". New Owner: \"%s\".)\n"),
		*m_name,
		*rParameters.name,
		m_spOwner.ReferencesObject() ? *m_spOwner->GetPath().ToString() : TXT("[none]"),
		rParameters.spOwner.ReferencesObject() ? *rParameters.spOwner->GetPath().ToString() : TXT("[none]"));

	// Only allow setting an empty name if no owner or instance index are given and this object has no children.
	if( name.IsEmpty() )
	{
		HELIUM_ASSERT( !pOwner );
		HELIUM_ASSERT( IsInvalid( instanceIndex ) );
		if( pOwner || IsValid( instanceIndex ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				( TXT( "Asset::Rename(): Objects cannot have name information cleared if being assigned an " )
				  TXT( "owner or instance index.\n" ) ) );

			return false;
		}

		HELIUM_ASSERT( !m_wpFirstChild );
		if( m_wpFirstChild )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "Asset::Rename(): Cannot clear name information for objects with children.\n" ) );

			return false;
		}
	}

	// Don't allow setting the owner to ourself.
	if( pOwner == this )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Cannot set the owner of an object to itself.\n" ) );

		return false;
	}

	// Don't allow setting the owner to an object with no name information.
	if( pOwner && pOwner->m_name.IsEmpty() )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "Asset::Rename(): Cannot set the owner of an object to an object with no path information.\n" ) );

		return false;
	}

	if( IsPackage() )
	{
		// Don't allow package objects to be children of non-package objects.
		if( pOwner && !pOwner->IsPackage() )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "Asset::Rename(): Cannot set a non-package as the owner of a package.\n" ) );

			return false;
		}

		// Don't allow instance indexing for packages.
		if( IsValid( instanceIndex ) )
		{
			HELIUM_TRACE(
				TraceLevels::Error,
				TXT( "Asset::Rename(): Instance indexing not supported for packages.\n" ) );

			return false;
		}
	}

	// Don't need to do anything if the name, owner, and instance index are not changing.
	if( name == m_name &&
		pOwner == m_spOwner &&
		( instanceIndex == m_instanceIndex || ( instanceIndex == INSTANCE_INDEX_AUTO && IsValid( m_instanceIndex ) ) ) )
	{
		return true;
	}

	// Hold onto a reference to the current owner until we return from this function.  This is done in case this object
	// has the last strong reference to it, in which case we would encounter a deadlock if clearing its reference while
	// we still have a write lock on the object list (object destruction also requires acquiring a write lock).
	AssetPtr spOldOwner = m_spOwner;

	{
		// Acquire a write lock on the object list to prevent objects from being added and removed as well as keep
		// objects from being renamed while this object is being renamed.
		ScopeWriteLock scopeLock( sm_objectListLock );

		// Get the list of children belonging to the new owner.
		AssetWPtr& rwpOwnerFirstChild = ( pOwner ? pOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

		// Don't check for name clashes if we're clearing the object path name information.
		if( !name.IsEmpty() )
		{
			// Resolve name clashes either through the instance index lookup map (if an instance index will be assigned)
			// or through a child object search (if no instance index will be used).
			if( IsValid( instanceIndex ) )
			{
				// Get the instance index map for the requested object name.
				ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();
				HELIUM_ASSERT( sm_pEmptyNameInstanceIndexMap );
				HELIUM_ASSERT( sm_pEmptyInstanceIndexSet );

				sm_pEmptyNameInstanceIndexMap->First() = ( pOwner ? pOwner->GetPath() : AssetPath( NULL_NAME ) );
				sm_pEmptyInstanceIndexSet->First() = name;

				ChildNameInstanceIndexMap::Accessor childNameMapAccessor;
				rNameInstanceIndexMap.Insert( childNameMapAccessor, *sm_pEmptyNameInstanceIndexMap );

				NameInstanceIndexMap::Accessor indexSetAccessor;
				childNameMapAccessor->Second().Insert( indexSetAccessor, *sm_pEmptyInstanceIndexSet );

				InstanceIndexSet& rIndexSet = indexSetAccessor->Second();
				InstanceIndexSet::ConstAccessor indexAccessor;

				if( instanceIndex == INSTANCE_INDEX_AUTO )
				{
					// Pick an unused instance index.
					instanceIndex = 0;
					while( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
					{
						++instanceIndex;
						HELIUM_ASSERT( instanceIndex < INSTANCE_INDEX_AUTO );
					}
				}
				else
				{
					// Attempt to acquire the specified instance index.
					if( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
					{
						HELIUM_TRACE(
							TraceLevels::Error,
							( TXT( "Asset::Rename(): Object already exists with the specified owner (%s), name " )
							  TXT( "(%s), and instance index (%" ) PRIu32 ").\n" ),
							( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
							*name,
							instanceIndex );

						return false;
					}
				}
			}
			else
			{
				// Check each child of the new owner for a name clash.
				for( Asset* pChild = rwpOwnerFirstChild; pChild != NULL; pChild = pChild->m_wpNextSibling )
				{
					if( pChild->m_name == name && pChild->m_instanceIndex == instanceIndex )
					{
						HELIUM_TRACE(
							TraceLevels::Error,
							( TXT( "Asset::Rename(): Object already exists with the specified owner (%s) and " )
							  TXT( "name (%s).\n" ) ),
							( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
							*name );

						return false;
					}
				}
			}
		}

		// Remove any old instance index tracking for the old path name.
		if( IsValid( m_instanceIndex ) )
		{
			AssetPath ownerPath = ( spOldOwner ? spOldOwner->GetPath() : AssetPath( NULL_NAME ) );

			ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();

			ChildNameInstanceIndexMap::Accessor childMapAccessor;
			HELIUM_VERIFY( rNameInstanceIndexMap.Find( childMapAccessor, ownerPath ) );

			NameInstanceIndexMap& rNameMap = childMapAccessor->Second();
			NameInstanceIndexMap::Accessor nameMapAccessor;
			HELIUM_VERIFY( rNameMap.Find( nameMapAccessor, m_name ) );

			InstanceIndexSet& rIndexSet = nameMapAccessor->Second();
			HELIUM_VERIFY( rIndexSet.Remove( m_instanceIndex ) );

			/*
			if( rIndexSet.IsEmpty() )
			{
				HELIUM_VERIFY( rNameMap.Remove( nameMapAccessor ) );
				if( rNameMap.IsEmpty() )
				{
					HELIUM_VERIFY( rNameInstanceIndexMap.Remove( childMapAccessor ) );
				}
			}
			*/
		}

		// If the owner of this object is changing, remove this object from its old owner's list and add it to the new
		// owner.
		if( spOldOwner.Get() != pOwner || ( m_name.IsEmpty() ? !name.IsEmpty() : name.IsEmpty() ) )
		{
			// Object should not be in any child object lists if its name is empty.
			if( !m_name.IsEmpty() )
			{
				AssetWPtr& rwpOldOwnerFirstChild =
					( spOldOwner ? spOldOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

				Asset* pPreviousChild = NULL;
				Asset* pChild = rwpOldOwnerFirstChild;
				while( pChild )
				{
					if( pChild == this )
					{
						( pPreviousChild ? pPreviousChild->m_wpNextSibling : rwpOldOwnerFirstChild ) = m_wpNextSibling;
						m_wpNextSibling.Release();

						break;
					}

					pPreviousChild = pChild;
					pChild = pChild->m_wpNextSibling;
				}
			}

			// If you assert here, it's possible that sm_wpFirstTopLevelObject is null. This can happen if an asset is destroyed
			// after the asset system is shut down
			HELIUM_ASSERT( !m_wpNextSibling );

			// Only store the object in a child object list if it is being given a valid name.
			if( !name.IsEmpty() )
			{
				m_wpNextSibling = rwpOwnerFirstChild;
				rwpOwnerFirstChild = this;
			}
		}

		// Set the new path name.
		m_name = name;
		m_spOwner = pOwner;
		m_instanceIndex = instanceIndex;

		// Update path information for this object and its children.
		UpdatePath();
	}

	return true;
}