const FilePath *Helium::Asset::GetAssetFileSystemPath() { HELIUM_ASSERT( !m_path.IsEmpty() ); FilePath filePath; Asset *pSourceAsset = GetSourceAsset(); if (pSourceAsset) { Package *pPackage = Reflect::SafeCast<Package>( pSourceAsset->GetOwner() ); if ( pPackage ) { PackageLoader *pLoader = pPackage->GetLoader(); HELIUM_ASSERT( pLoader->HasAssetFileState() ); if ( pLoader ) { return &pLoader->GetAssetFileSystemPath( pSourceAsset->GetPath() ); } } } return NULL; }
int64_t AssetLoader::GetAssetFileTimestamp( const AssetPath &path ) { Package *pPackage = Asset::Find<Package>( path.GetParent() ); HELIUM_ASSERT( pPackage ); PackageLoader *pLoader = pPackage->GetLoader(); HELIUM_ASSERT( pLoader ); return pLoader->GetAssetFileSystemTimestamp( path ); }
bool Helium::Asset::SaveAsset() { Package *pPackage = GetOwningPackage(); if ( pPackage ) { PackageLoader *pLoader = pPackage->GetLoader(); if ( pLoader ) { pLoader->SaveAsset( this ); return true; } } return false; }
void ProjectPanel::OnSave( wxCommandEvent& event ) { wxDataViewItemArray selection; int numSelected = m_DataViewCtrl->GetSelections( selection ); for (int i = 0; i < numSelected; ++i) { Asset *pAsset = static_cast<Asset *>( selection[i].GetID() ); Package *pPackage = pAsset->GetOwningPackage(); HELIUM_ASSERT( pPackage ); PackageLoader *pPackageLoader = pPackage->GetLoader(); HELIUM_ASSERT( pPackageLoader ); pPackageLoader->SaveAsset( pAsset ); } }
int lua::DefaultPackageLoaderCallback(lua_State* L) { const char* name = lua_tostring(L, 1); PackageLoader* loader = (PackageLoader*)lua_topointer(L, lua_upvalueindex(1)); LoadedPackage data; if( !loader || !loader->pfn ) { lua_pushstring(L, "package loader initialization error"); return 1; } else { data = loader->pfn(loader->userdata, name); if( data.bytes != NULL ) { eiASSERT( data.numBytes && data.filename ); eiDEBUG( int ok = ) luaL_loadbuffer(L, data.bytes, data.numBytes, data.filename); eiASSERT( ok == 0 ); lua_pushstring(L, data.filename); return 2; } }
uint64_t Helium::Asset::GetAssetFileTimeStamp() { HELIUM_ASSERT( !m_path.IsEmpty() ); uint64_t timestamp = 0; Asset *pSourceAsset = GetSourceAsset(); if (pSourceAsset) { Package *pPackage = Reflect::SafeCast<Package>( pSourceAsset->GetOwner() ); if ( pPackage ) { PackageLoader *pLoader = pPackage->GetLoader(); HELIUM_ASSERT( pLoader->HasAssetFileState() ); if ( pLoader ) { pLoader->GetAssetFileSystemTimestamp( pSourceAsset->GetPath() ); } } } return timestamp; }
/// Update property preloading for the given object load request. /// /// @param[in] pRequest Load request to update. /// /// @return True if preloading still needs processing, false if it is complete. bool GameObjectLoader::TickPreload( LoadRequest* pRequest ) { HELIUM_ASSERT( pRequest ); HELIUM_ASSERT( !( pRequest->stateFlags & ( LOAD_FLAG_LINKED | LOAD_FLAG_PRECACHED | LOAD_FLAG_LOADED ) ) ); PackageLoader* pPackageLoader = pRequest->pPackageLoader; HELIUM_ASSERT( pPackageLoader ); if( IsInvalid( pRequest->packageLoadRequestId ) ) { if( !pPackageLoader->TryFinishPreload() ) { // Still waiting for package loader preload. return false; } // Add an object load request. GameObjectPath path = pRequest->path; pRequest->packageLoadRequestId = pPackageLoader->BeginLoadObject( path ); if( IsInvalid( pRequest->packageLoadRequestId ) ) { pRequest->spObject = GameObject::FindObject( path ); GameObject* pObject = pRequest->spObject; if( pObject ) { HELIUM_TRACE( TRACE_WARNING, TXT( "GameObjectLoader: GameObject \"%s\" is not serialized, but was found in memory.\n" ), *path.ToString() ); // Make sure the object is preloaded and linked, but still perform resource caching and load // finalization if necessary. pObject->SetFlags( GameObject::FLAG_PRELOADED | GameObject::FLAG_LINKED ); AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRELOADED | LOAD_FLAG_LINKED ); return true; } HELIUM_TRACE( TRACE_ERROR, TXT( "GameObjectLoader: GameObject \"%s\" is not serialized and does not exist in memory.\n" ), *path.ToString() ); AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_FULLY_LOADED | LOAD_FLAG_ERROR ); return true; } } HELIUM_ASSERT( IsValid( pRequest->packageLoadRequestId ) ); bool bFinished = pPackageLoader->TryFinishLoadObject( pRequest->packageLoadRequestId, pRequest->spObject, pRequest->linkTable ); if( !bFinished ) { // Still waiting for object to load. return false; } // Preload complete. SetInvalid( pRequest->packageLoadRequestId ); AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRELOADED ); return true; }
void ForciblyFullyLoadedPackageManager::Tick() { AssetLoader *pAssetLoader = AssetLoader::GetStaticInstance(); // For each editable package for ( DynamicArray< ForciblyFullyLoadedPackage >::Iterator packageIter = m_ForciblyFullyLoadedPackages.Begin(); packageIter != m_ForciblyFullyLoadedPackages.End(); ++packageIter) { ForciblyFullyLoadedPackage &package = *packageIter; // Load the package if we need to if ( Helium::IsValid< size_t >( package.m_PackageLoadId ) ) { HELIUM_ASSERT( package.m_Assets.IsEmpty() ); HELIUM_ASSERT( package.m_AssetLoadIds.IsEmpty() ); HELIUM_ASSERT( package.m_AssetPaths.IsEmpty() ); HELIUM_ASSERT( !package.m_Package ); AssetPtr packagePtr; if ( pAssetLoader->TryFinishLoad( package.m_PackageLoadId, packagePtr ) ) { // Load request is finished. package.m_PackageLoadId = Helium::Invalid< size_t >(); package.m_Package = Reflect::AssertCast<Package>(packagePtr); if ( package.m_Package ) { if ( !package.m_Package->GetAllFlagsSet( Asset::FLAG_EDITOR_FORCIBLY_LOADED ) ) { // Package loaded successfully, queue load requests for all children package.m_Package->SetFlags( Asset::FLAG_EDITOR_FORCIBLY_LOADED ); e_AssetForciblyLoadedEvent.Raise( AssetEventArgs( package.m_Package ) ); } PackageLoader *pLoader = package.m_Package->GetLoader(); pLoader->EnumerateChildren( package.m_AssetPaths ); package.m_Assets.Resize( package.m_AssetPaths.GetSize() ); package.m_AssetLoadIds.Resize( package.m_AssetPaths.GetSize() ); DynamicArray< AssetPath >::Iterator assetPathIter = package.m_AssetPaths.Begin(); DynamicArray< size_t >::Iterator assetLoadIdIter = package.m_AssetLoadIds.Begin(); int i = 0; for ( ; assetPathIter != package.m_AssetPaths.End(); ++assetPathIter, ++assetLoadIdIter ) { *assetLoadIdIter = pAssetLoader->BeginLoadObject( *assetPathIter ); HELIUM_ASSERT( !package.m_Assets[i++] ); } } else { HELIUM_TRACE( TraceLevels::Warning, "Failed to load package '%s' for editor.", *package.m_PackagePath.ToString()); } } } } // For each editable package for ( DynamicArray< ForciblyFullyLoadedPackage >::Iterator packageIter = m_ForciblyFullyLoadedPackages.Begin(); packageIter != m_ForciblyFullyLoadedPackages.End(); ++packageIter) { ForciblyFullyLoadedPackage &package = *packageIter; // If the package is loaded if ( package.m_Package ) { // Load the child assets if we need to for ( int i = 0; i < package.m_AssetPaths.GetSize(); ++i ) { if ( Helium::IsValid<size_t>( package.m_AssetLoadIds[i] ) ) { HELIUM_ASSERT( !package.m_Assets[i] ); if ( pAssetLoader->TryFinishLoad( package.m_AssetLoadIds[i], package.m_Assets[i] ) ) { package.m_AssetLoadIds[i] = Invalid< size_t >(); if ( package.m_Assets[i] ) { // Asset loaded successfully if ( !package.m_Assets[i]->IsPackage() && !package.m_Assets[i]->GetAllFlagsSet( Asset::FLAG_EDITOR_FORCIBLY_LOADED ) ) { package.m_Assets[i]->SetFlags( Asset::FLAG_EDITOR_FORCIBLY_LOADED ); e_AssetForciblyLoadedEvent.Raise( AssetEventArgs( package.m_Assets[i] ) ); } } else { HELIUM_TRACE( TraceLevels::Warning, "Failed to asset '%s' for editor.", *package.m_PackagePath.ToString()); } } else { HELIUM_ASSERT( !package.m_Assets[i] ); } if ( Helium::IsValid<size_t>( package.m_AssetLoadIds[i] ) ) { HELIUM_ASSERT( !package.m_Assets[i] ); } } } } } }
/// Begin asynchronous loading of a shader variant. /// /// @param[in] pShader Parent shader resource. /// @param[in] shaderType Shader type. /// @param[in] userOptionIndex Index associated with the user option combination for the shader variant. /// /// @return ID associated with the load procedure, or an invalid index if the load could not be started. /// /// @see TryFinishLoadVariant() size_t ShaderVariantResourceHandler::BeginLoadVariant( Shader* pShader, RShader::EType shaderType, uint32_t userOptionIndex ) { HELIUM_ASSERT( pShader ); HELIUM_ASSERT( static_cast< size_t >( shaderType ) < static_cast< size_t >( RShader::TYPE_MAX ) ); // Attempt to locate an existing load request for the specified shader variant. LoadRequest* pLoadRequest = m_loadRequestPool.Allocate(); HELIUM_ASSERT( pLoadRequest ); pLoadRequest->shaderType = shaderType; pLoadRequest->userOptionIndex = userOptionIndex; HELIUM_ASSERT( !pLoadRequest->spVariant ); pLoadRequest->requestCount = 1; LoadRequestSetType::ConstAccessor loadRequestConstAccessor; if( !m_loadRequestSet.Insert( loadRequestConstAccessor, pLoadRequest ) ) { // Request exists, so increment its reference count. m_loadRequestPool.Release( pLoadRequest ); pLoadRequest = *loadRequestConstAccessor; HELIUM_ASSERT( pLoadRequest ); AtomicIncrementAcquire( pLoadRequest->requestCount ); size_t loadId = m_loadRequestPool.GetIndex( pLoadRequest ); HELIUM_ASSERT( IsValid( loadId ) ); return loadId; } // Adding a new request, so create the variant object if it does not yet exist. tchar_t shaderTypeCharacter; if( shaderType == RShader::TYPE_VERTEX ) { shaderTypeCharacter = TXT( 'v' ); } else { HELIUM_ASSERT( shaderType == RShader::TYPE_PIXEL ); shaderTypeCharacter = TXT( 'p' ); } String variantNameString; variantNameString.Format( TXT( "%c%" ) TPRIu32, shaderTypeCharacter, userOptionIndex ); Name variantName( variantNameString ); variantNameString.Clear(); pLoadRequest->spVariant.Set( Reflect::AssertCast< ShaderVariant >( pShader->FindChild( variantName ) ) ); if( !pLoadRequest->spVariant ) { if( !GameObject::Create< ShaderVariant >( pLoadRequest->spVariant, variantName, pShader ) ) { HELIUM_TRACE( TRACE_ERROR, ( TXT( "ShaderVariantResourceHandler::BeginLoadVariant(): Failed to create shader variant object " ) TXT( "\"%s:%s\".\n" ) ), *pShader->GetPath().ToString(), *variantName ); } else { HELIUM_ASSERT( pLoadRequest->spVariant ); } } // If we have an object for the shader variant, attempt to load its resource data. ShaderVariant* pVariant = pLoadRequest->spVariant; if( pVariant && !pVariant->GetAnyFlagSet( GameObject::FLAG_PRECACHED ) ) { GameObject* pPackageObject; for( pPackageObject = pShader->GetOwner(); pPackageObject != NULL && !pPackageObject->IsPackage(); pPackageObject = pPackageObject->GetOwner() ) { // This space intentionally left blank... } HELIUM_ASSERT( pPackageObject ); PackageLoader* pPackageLoader = Reflect::AssertCast< Package >( pPackageObject )->GetLoader(); HELIUM_ASSERT( pPackageLoader ); HELIUM_ASSERT( pPackageLoader->IsSourcePackageFile() ); ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::GetStaticInstance(); HELIUM_ASSERT( pObjectPreprocessor ); pObjectPreprocessor->LoadResourceData( pVariant, pPackageLoader->GetFileTimestamp() ); // Resource data loaded, so deserialize the persistent data for the current platform and begin precaching. CacheManager& rCacheManager = CacheManager::GetStaticInstance(); const Resource::PreprocessedData& rPreprocessedData = pVariant->GetPreprocessedData( rCacheManager.GetCurrentPlatform() ); const DynArray< uint8_t >& rPersistentDataBuffer = rPreprocessedData.persistentDataBuffer; //PMDTODO: Implmenet this // BinaryDeserializer deserializer; // deserializer.Prepare( rPersistentDataBuffer.GetData(), rPersistentDataBuffer.GetSize() ); // deserializer.BeginSerialize(); // pVariant->SerializePersistentResourceData( deserializer ); // deserializer.EndSerialize(); Reflect::ObjectPtr persistent_resource_data = Cache::ReadCacheObjectFromBuffer(rPersistentDataBuffer); pVariant->LoadPersistentResourceObject(persistent_resource_data); pVariant->BeginPrecacheResourceData(); } size_t loadId = m_loadRequestPool.GetIndex( pLoadRequest ); HELIUM_ASSERT( IsValid( loadId ) ); return loadId; }
/// @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; }