/// Perform a non-blocking attempt to sync with an asynchronous shader variant load request. /// /// @param[in] loadId Load request ID. /// @param[out] rspVariant Smart pointer set to the variant reference if loading has completed. /// /// @return True if loading has completed, false if not. Note that if this returns true, the load request ID will /// no longer be valid for its current load request and should not be reused. /// /// @see BeginLoadVariant() bool Shader::TryFinishLoadVariant( size_t loadId, ShaderVariantPtr& rspVariant ) { HELIUM_ASSERT( IsValid( loadId ) ); // Use the try-finish-load override if one is registered. if( sm_pTryFinishLoadVariantOverride ) { bool bFinished = sm_pTryFinishLoadVariantOverride( sm_pVariantLoadOverrideData, loadId, rspVariant ); return bFinished; } // Attempt to sync the object load request. GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance(); HELIUM_ASSERT( pObjectLoader ); GameObjectPtr spObject; bool bFinished = pObjectLoader->TryFinishLoad( loadId, spObject ); if( bFinished ) { rspVariant = Reflect::AssertCast< ShaderVariant >( spObject.Get() ); } return bFinished; }
/// @copydoc Serializer::SerializeObjectReference() void BinarySerializer::SerializeObjectReference( const GameObjectType* /*pType*/, GameObjectPtr& rspObject ) { if( ShouldSerializeCurrentProperty() ) { HELIUM_ASSERT( m_bAllowObjectReferences ); if( !m_bAllowObjectReferences ) { HELIUM_TRACE( TRACE_ERROR, ( TXT( "BinarySerializer: Attempted to serialize an object reference using a serializer with " ) TXT( "which it is not allowed.\n" ) ) ); return; } uint32_t objectIndex; SetInvalid( objectIndex ); GameObject* pObject = rspObject.Get(); if( pObject ) { objectIndex = ResolveObjectDependency( pObject->GetPath() ); HELIUM_ASSERT( IsValid( objectIndex ) ); } m_pPropertyStream->Write( &objectIndex, sizeof( objectIndex ), 1 ); } }
/// 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 GameObject::Rename( const RenameParameters& rParameters ) { Name name = rParameters.name; GameObject* pOwner = rParameters.spOwner; uint32_t instanceIndex = rParameters.instanceIndex; HELIUM_TRACE( TraceLevels::Debug, TXT("GameObject::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( "GameObject::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( "GameObject::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( "GameObject::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( "GameObject::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( "GameObject::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( "GameObject::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). GameObjectPtr 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. GameObjectWPtr& 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() : GameObjectPath( 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( "GameObject::Rename(): Object already exists with the specified owner (%s), name " ) TXT( "(%s), and instance index (%" ) TPRIu32 TXT( ").\n" ) ), ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ), *name, instanceIndex ); return false; } } } else { // Check each child of the new owner for a name clash. for( GameObject* pChild = rwpOwnerFirstChild; pChild != NULL; pChild = pChild->m_wpNextSibling ) { if( pChild->m_name == name && pChild->m_instanceIndex == instanceIndex ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "GameObject::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 ) ) { GameObjectPath ownerPath = ( spOldOwner ? spOldOwner->GetPath() : GameObjectPath( 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() ) { GameObjectWPtr& rwpOldOwnerFirstChild = ( spOldOwner ? spOldOwner->m_wpFirstChild : sm_wpFirstTopLevelObject ); GameObject* pPreviousChild = NULL; GameObject* pChild = rwpOldOwnerFirstChild; while( pChild ) { if( pChild == this ) { ( pPreviousChild ? pPreviousChild->m_wpNextSibling : rwpOldOwnerFirstChild ) = m_wpNextSibling; m_wpNextSibling.Release(); break; } pPreviousChild = pChild; pChild = pChild->m_wpNextSibling; } } 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; }
/// Initialize all resources provided by this manager. /// /// @see Shutdown(), PostConfigUpdate() void RenderResourceManager::Initialize() { // Release any existing resources. Shutdown(); // Get the renderer and graphics configuration. Renderer* pRenderer = Renderer::GetStaticInstance(); if( !pRenderer ) { return; } Config& rConfig = Config::GetStaticInstance(); StrongPtr< GraphicsConfig > spGraphicsConfig( rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) ); if( !spGraphicsConfig ) { HELIUM_TRACE( TRACE_ERROR, TXT( "RenderResourceManager::Initialize(): Initialization failed; missing GraphicsConfig.\n" ) ); return; } // 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. #pragma TODO( "XXX TMC: Migrate to a more data-driven solution." ) GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance(); HELIUM_ASSERT( pObjectLoader ); GameObjectPath prePassShaderPath; HELIUM_VERIFY( prePassShaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "PrePass.hlsl" ) ) ); GameObjectPtr spPrePassShader; HELIUM_VERIFY( pObjectLoader->LoadObject( prePassShaderPath, spPrePassShader ) ); Shader* pPrePassShader = Reflect::SafeCast< Shader >( spPrePassShader.Get() ); HELIUM_ASSERT( pPrePassShader ); if( pPrePassShader ) { size_t loadId = pPrePassShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pPrePassShader->TryFinishLoadVariant( loadId, m_spPrePassVertexShader ) ) { pObjectLoader->Tick(); } } } // Attempt to load the simple world-space, simple screen-space, and screen-space text shaders. #pragma TODO( "XXX TMC: Migrate to a more data-driven solution." ) GameObjectPath shaderPath; GameObjectPtr spShader; Shader* pShader; HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "Simple.hlsl" ) ) ); HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) ); pShader = Reflect::SafeCast< Shader >( spShader.Get() ); HELIUM_ASSERT( pShader ); if( pShader ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpaceVertexShader ) ) { pObjectLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpacePixelShader ) ) { pObjectLoader->Tick(); } } } HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "ScreenSpaceTexture.hlsl" ) ) ); HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) ); pShader = Reflect::SafeCast< Shader >( spShader.Get() ); HELIUM_ASSERT( pShader ); if( pShader ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpaceVertexShader ) ) { pObjectLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpacePixelShader ) ) { pObjectLoader->Tick(); } } } HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "ScreenText.hlsl" ) ) ); HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) ); pShader = Reflect::SafeCast< Shader >( spShader.Get() ); HELIUM_ASSERT( pShader ); if( pShader ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextVertexShader ) ) { pObjectLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if( IsValid( loadId ) ) { while( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextPixelShader ) ) { pObjectLoader->Tick(); } } } // Attempt to load the debug fonts. #pragma TODO( "XXX TMC: Migrate to a more data-driven solution." ) GameObjectPath fontPath; GameObjectPtr spFont; HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugSmall" ) ) ); HELIUM_VERIFY( pObjectLoader->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 TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugMedium" ) ) ); HELIUM_VERIFY( pObjectLoader->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 TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugLarge" ) ) ); HELIUM_VERIFY( pObjectLoader->LoadObject( fontPath, spFont ) ); m_debugFonts[ DEBUG_FONT_SIZE_LARGE ] = Reflect::SafeCast< Font >( spFont.Get() ); spFont.Release(); }
/// Create the default world instance. /// /// @param[in] pType World type. /// /// @return Default world instance. World* WorldManager::CreateDefaultWorld( const GameObjectType* pType ) { HELIUM_ASSERT( pType ); if( !pType ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): No world type specified.\n" ) ); return NULL; } bool bIsWorldType = pType->GetClass()->IsType( World::GetStaticType()->GetClass() ); HELIUM_ASSERT( bIsWorldType ); if( !bIsWorldType ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): Type \"%s\" specified is not a World subtype.\n" ), *pType->GetName() ); return NULL; } HELIUM_ASSERT( m_spWorldPackage ); if( !m_spWorldPackage ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): World manager has not been initialized.\n" ) ); return NULL; } HELIUM_ASSERT( m_worlds.IsEmpty() ); if( !m_worlds.IsEmpty() ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): Default world has already been created.\n" ) ); return NULL; } GameObjectPtr spDefaultWorldObject; bool bCreateResult = GameObject::CreateObject( spDefaultWorldObject, pType, GetDefaultWorldName(), m_spWorldPackage ); HELIUM_ASSERT( bCreateResult ); if( !bCreateResult ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): Failed to create world of type \"%s\".\n" ), *pType->GetName() ); return NULL; } WorldPtr spDefaultWorld( Reflect::AssertCast< World >( spDefaultWorldObject.Get() ) ); HELIUM_ASSERT( spDefaultWorld ); m_worlds.Push( spDefaultWorld ); return spDefaultWorld; }