/// Recursive function for resolving a package request. /// /// @param[out] rspPackage Resolved package. /// @param[in] packagePath Package object path. void CachePackageLoader::ResolvePackage( GameObjectPtr& rspPackage, GameObjectPath packagePath ) { HELIUM_ASSERT( !packagePath.IsEmpty() ); rspPackage = GameObject::FindObject( packagePath ); if( !rspPackage ) { GameObjectPtr spParent; GameObjectPath parentPath = packagePath.GetParent(); if( !parentPath.IsEmpty() ) { ResolvePackage( spParent, parentPath ); HELIUM_ASSERT( spParent ); } HELIUM_VERIFY( GameObject::CreateObject( rspPackage, Package::GetStaticType(), packagePath.GetName(), spParent ) ); HELIUM_ASSERT( rspPackage ); HELIUM_ASSERT( rspPackage->IsClass( Package::GetStaticType()->GetClass() ) ); } rspPackage->SetFlags( GameObject::FLAG_PRELOADED | GameObject::FLAG_LINKED | GameObject::FLAG_LOADED ); }
/// Find an object based on its path name. /// /// @param[in] path FilePath of the object to locate. /// /// @return Pointer to the object if found, null pointer if not found. GameObject* GameObject::FindObject( GameObjectPath path ) { // Make sure the path isn't empty. if( path.IsEmpty() ) { return NULL; } // Assemble a list of object names and instance indices, from the top level on down. size_t pathDepth = 0; size_t packageDepth = 0; for( GameObjectPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { ++pathDepth; if( testPath.IsPackage() ) { ++packageDepth; } } StackMemoryHeap<>& rStackHeap = ThreadLocalStackAllocator::GetMemoryHeap(); StackMemoryHeap<>::Marker stackMarker( rStackHeap ); Name* pPathNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * pathDepth ) ); HELIUM_ASSERT( pPathNames ); uint32_t* pInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * pathDepth ) ); HELIUM_ASSERT( pInstanceIndices ); size_t pathIndex = pathDepth; for( GameObjectPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { HELIUM_ASSERT( pathIndex != 0 ); --pathIndex; pPathNames[ pathIndex ] = testPath.GetName(); pInstanceIndices[ pathIndex ] = testPath.GetInstanceIndex(); } HELIUM_ASSERT( pathIndex == 0 ); // Search from the root. return FindChildOf( NULL, pPathNames, pInstanceIndices, pathDepth, packageDepth ); }
/// Get the path to the package containing all world instances. /// /// @return World package path. GameObjectPath WorldManager::GetWorldPackagePath() const { static GameObjectPath worldPackagePath; if( worldPackagePath.IsEmpty() ) { HELIUM_VERIFY( worldPackagePath.Set( TXT( "/Worlds" ) ) ); } return worldPackagePath; }
/// Resolve a dependency on an object reference. /// /// @param[in] path Object path. /// /// @return Dependency index. /// /// @see ResolveTypeDependency() uint32_t BinarySerializer::ResolveObjectDependency( GameObjectPath path ) { uint32_t objectIndex; SetInvalid( objectIndex ); if( !path.IsEmpty() ) { size_t dependencyCount = m_objectDependencies.GetSize(); for( size_t dependencyIndex = 0; dependencyIndex < dependencyCount; ++dependencyIndex ) { if( m_objectDependencies[ dependencyIndex ] == path ) { return static_cast< uint32_t >( dependencyIndex ); } } HELIUM_ASSERT( dependencyCount < UINT32_MAX ); m_objectDependencies.Push( path ); objectIndex = static_cast< uint32_t >( dependencyCount ); } return objectIndex; }
/// Initialize this manager. /// /// @return True if this manager was initialized successfully, false if not. /// /// @see Shutdown() bool WorldManager::Initialize() { HELIUM_ASSERT( !m_spWorldPackage ); // Create the world package first. // XXX TMC: Note that we currently assume that the world package has no parents, so we don't need to handle // recursive package creation. If we want to move the world package to a subpackage, this will need to be // updated accordingly. GameObjectPath worldPackagePath = GetWorldPackagePath(); HELIUM_ASSERT( !worldPackagePath.IsEmpty() ); HELIUM_ASSERT( worldPackagePath.GetParent().IsEmpty() ); bool bCreateResult = GameObject::Create< Package >( m_spWorldPackage, worldPackagePath.GetName(), NULL ); HELIUM_ASSERT( bCreateResult ); if( !bCreateResult ) { HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::Initialize(): Failed to create world package \"%s\".\n" ), *worldPackagePath.ToString() ); return false; } HELIUM_ASSERT( m_spWorldPackage ); // Reset frame timings. m_actualFrameTickCount = 0; m_frameTickCount = 0; m_frameDeltaTickCount = 0; m_frameDeltaSeconds = 0.0f; // First frame still needs to be processed. m_bProcessedFirstFrame = false; return true; }
/// @copydoc GameObjectLoader::CacheObject() bool EditorObjectLoader::CacheObject( GameObject* pObject, bool bEvictPlatformPreprocessedResourceData ) { HELIUM_ASSERT( pObject ); // Don't cache broken objects or packages. if( pObject->GetAnyFlagSet( GameObject::FLAG_BROKEN ) || pObject->IsPackage() ) { return false; } // Make sure we have an object preprocessor instance with which to cache the object. ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::GetStaticInstance(); if( !pObjectPreprocessor ) { HELIUM_TRACE( TRACE_WARNING, TXT( "EditorObjectLoader::CacheObject(): Missing ObjectPreprocessor to use for caching.\n" ) ); return false; } // Configuration objects should not be cached. GameObjectPath objectPath = pObject->GetPath(); Config& rConfig = Config::GetStaticInstance(); GameObjectPath configPackagePath = rConfig.GetConfigContainerPackagePath(); HELIUM_ASSERT( !configPackagePath.IsEmpty() ); for( GameObjectPath testPath = objectPath; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { if( testPath == configPackagePath ) { return false; } } // Get the timestamp for the object based on the timestamp of its source package file and, if it's a resource, // the timestamp of the source resource file. GameObject* pPackageObject; for( pPackageObject = pObject; pPackageObject && !pPackageObject->IsPackage(); pPackageObject = pPackageObject->GetOwner() ) { } HELIUM_ASSERT( pPackageObject ); PackageLoader* pPackageLoader = Reflect::AssertCast< Package >( pPackageObject )->GetLoader(); HELIUM_ASSERT( pPackageLoader ); HELIUM_ASSERT( pPackageLoader->IsSourcePackageFile() ); int64_t objectTimestamp = pPackageLoader->GetFileTimestamp(); if( !pObject->IsDefaultTemplate() ) { Resource* pResource = Reflect::SafeCast< Resource >( pObject ); if( pResource ) { GameObjectPath baseResourcePath = pResource->GetPath(); HELIUM_ASSERT( !baseResourcePath.IsPackage() ); for( ; ; ) { GameObjectPath parentPath = baseResourcePath.GetParent(); if( parentPath.IsEmpty() || parentPath.IsPackage() ) { break; } baseResourcePath = parentPath; } Path sourceFilePath; if ( !File::GetDataDirectory( sourceFilePath ) ) { HELIUM_TRACE( TRACE_WARNING, TXT( "EditorObjectLoader::CacheObject(): Could not obtain data directory.\n" ) ); return false; } sourceFilePath += baseResourcePath.ToFilePathString().GetData(); int64_t sourceFileTimestamp = sourceFilePath.ModifiedTime(); if( sourceFileTimestamp > objectTimestamp ) { objectTimestamp = sourceFileTimestamp; } } } // Cache the object. bool bSuccess = pObjectPreprocessor->CacheObject( pObject, objectTimestamp, bEvictPlatformPreprocessedResourceData ); if( !bSuccess ) { HELIUM_TRACE( TRACE_ERROR, TXT( "EditorObjectLoader: Failed to cache object \"%s\".\n" ), *objectPath.ToString() ); } return bSuccess; }