HRESULT ParaEngine::CCCSFaceLoader::Load() { if (CParaFile::DoesFileExist(m_sFileName.c_str(), false)) return S_OK; // check if all textures involved are loaded. for (int i = 0; i < CFS_TOTAL_NUM; ++i) { FaceTextureComponent& component = m_layers[i]; if (component.name.empty()) continue; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(component.name); if (pEntry) { if (!pEntry->DoesFileExist()) { m_pAssetFileEntry = pEntry; return E_PENDING; } } } #ifdef USE_DIRECTX_RENDERER return ComposeWithGDIPlus(); #else return S_OK; #endif }
int CParaFile::OpenAssetFile(const char* filename, bool bDownloadIfNotUpToDate, const char* relativePath) { if (relativePath != NULL) { int nRes = OpenAssetFile(filename, bDownloadIfNotUpToDate); if (nRes == 0) { // try relative path if not exist. char sNewFilename[MAX_PATH * 2]; CFileUtils::MakeFileNameFromRelativePath(sNewFilename, filename, relativePath); nRes = OpenAssetFile(sNewFilename, bDownloadIfNotUpToDate); } return nRes; } AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename); if (pEntry) { if (CParaFile::DoesFileExist(filename, false)) { CAsyncLoader::GetSingleton().log(string("ParaFile.OpenAssetFile using disk file:") + filename + "\n"); if (OpenFile(filename, true, relativePath)) return 1; else { OUTPUT_LOG("error: failed open disk file: %s\n", filename); } } if (pEntry->DoesFileExist()) { if (m_filename.empty()) m_filename = filename; return OpenFile(pEntry->GetLocalFileName().c_str(), true, relativePath) ? 1 : 0; } else { if (!bDownloadIfNotUpToDate) { return 0; } else { // download the file here. if (pEntry->SyncFile()) { // open the file now. if (m_filename.empty()) m_filename = filename; return OpenFile(pEntry->GetLocalFileName().c_str(), true, relativePath) ? 1 : 0; } } } } else { CAsyncLoader::GetSingleton().log(string("ParaFile.OpenAssetFile using local file:") + filename + "\n"); #ifdef PARAENGINE_MOBILE if (relativePath == NULL) { uint32 dwFound = FILE_NOT_FOUND; // check file existence, then open file will prevent file not found warnings in mobile version. if ((dwFound = CParaFile::DoesFileExist2(filename, FILE_ON_DISK | FILE_ON_ZIP_ARCHIVE | FILE_ON_SEARCH_PATH))) { return OpenFile(filename, true, relativePath, false, dwFound) ? 1 : 0; } return 0; } #endif return OpenFile(filename, true, relativePath) ? 1 : 0; } return 0; }
CAudioSource2_ptr ParaEngine::CAudioEngine2::Create(const char* sName, const char* sWavePath, bool bStream) { CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sName); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(!pWave) { pWave = new CAudioSource2(sName); iter->second = pWave; } if(pWave->m_pSource) { pWave->m_pSource->stop(); } } else { pWave = new CAudioSource2(sName); m_audio_file_map[sName] = pWave; } if(m_pAudioEngine == 0) return pWave; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; #ifdef PARAENGINE_MOBILE // streaming should be disabled since it is too slow on mobile disk. OUTPUT_LOG("streaming audio file %s is disabled since it is too slow on mobile disk\n", pEntry->GetLocalFileName().c_str()); bStream = false; #endif if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); // OUTPUT_LOG("info:streaming audio file from %s\n", filename.c_str()); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), true)) { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } else { OUTPUT_LOG("warning: failed to copy audio file from %s to %s\n", pEntry->GetLocalFileName().c_str(), filename.c_str()); } } else { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); // OUTPUT_LOG("info:playing in memory audio file from %s\n", pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sName, file.getBuffer(), file.getSize(), file_extension.c_str()); } else { OUTPUT_LOG("warning: failed to open audio file %s\n", pEntry->GetLocalFileName().c_str()); } } if(pSource) { pWave->SetSource(pSource); // if there is pending looped sound, we will play it. For non-looping sound that has just finished downloading, we will ignore it. if(pWave->m_bIsAsyncLoadingWhileLoopPlaying) { pWave->play2d(true); } } } else { CWaveFileDownloadCallBackData2 callBack(sName, sWavePath, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sName, sWavePath, bStream); if(pSource) { pWave->SetSource(pSource); } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { #ifdef PARAENGINE_MOBILE OUTPUT_LOG("audio file opened: %s \n", sWavePath); #endif std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave->SetSource(pSource); } } } } return pWave; }
HRESULT ParaEngine::CAudioEngine2::PlayWaveFile( const char* sWavePath, bool bLoop, bool bStream/*=false*/, int dwPlayOffset/*=0*/ ) { if(!IsValidAndEnabled() || GetGlobalVolume()<=0.f) return E_FAIL; // check if the wave file is already prepared before CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sWavePath); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(pWave && pWave->m_pSource) { if(pWave->m_pSource->isPlaying()) { // already playing, so return. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s already playing. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); #endif return S_OK; } } else { // it usually means that the music is pending for downloading. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s pending for download\n", sWavePath); #endif return S_OK; } } else { // prepare the wave file. bool bSucceed = false; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), false)) { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); } } if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } else { // push to the queue. m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); CWaveFilePlayCallBackData2 callBack(sWavePath, bLoop, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sWavePath, sWavePath, bStream); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: new audio %s prepared \n", sWavePath); #endif } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } } } if(!bSucceed) { m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); OUTPUT_LOG("unable to prepare wave file %s\r\n", sWavePath); return E_FAIL; } } // play the sound if(pWave) { if( ! (pWave->play2d(bLoop, false)) ) { return E_FAIL; } #ifdef DEBUG_AUDIO if(pWave->m_pSource) { OUTPUT_LOG("PlayWaveFile: play2d is called for %s. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); } #endif } return S_OK; }
HRESULT ParaEngine::CAudioEngine2::PrepareWaveFile( CAudioSource2_ptr& pWave, const char* sWavePath, bool bStream ) { // prepare the wave file. bool bSucceed = false; if(!pWave) return E_FAIL; if(pWave->GetSource() != NULL ) { OUTPUT_LOG("warning: repeated all to already prepared wave file %s\n", sWavePath); return S_OK; } AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetLocalFileName() + "."+ CParaFile::GetFileExtension(sWavePath); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), false)) { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); } } if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sWavePath, sWavePath, bStream); if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave->SetSource(pSource); bSucceed = true; } } } } return (bSucceed) ? S_OK : E_FAIL; }
HRESULT ParaEngine::CParaXProcessor::CopyToResource() { if (m_asset.get() == 0) return E_FAIL; if (m_asset->m_MeshLODs.size() == 0) { string filename = m_asset->GetLocalFileName(); bool bLoadHeaderFromXFile = true; bool bSingleLOD = true; bool bIsXML = (CParaFile::GetFileExtension(filename) == "xml"); string sParentDirectory = CParaFile::GetParentDirectoryFromPath(filename); // check in manifest AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename); if (pEntry) { if (pEntry->DoesFileExist()) { filename = pEntry->GetLocalFileName(); } else { m_pAssetFileEntry = pEntry; return E_PENDING; } } if (bIsXML) { CParaMeshXMLFile file; if (file.LoadFromFile(filename, sParentDirectory)) { if (file.GetType() == CParaMeshXMLFile::TYPE_MESH_LOD) { int i; // check if all sub files are available locally. for (i = 0; i < file.GetSubMeshCount(); ++i) { CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i); AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(pSubLODMesh->m_sFileName); if (pEntry) { if (pEntry->DoesFileExist()) { pSubLODMesh->m_sFileName = pEntry->GetLocalFileName(); } else { m_pAssetFileEntry = pEntry; return E_PENDING; } } } if (file.m_bHasBoundingBox) { } for (i = 0; i < file.GetSubMeshCount(); ++i) { CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i); CreateMeshLODLevel(pSubLODMesh->m_fToCameraDist, pSubLODMesh->m_sFileName); } if (file.GetSubMeshCount() == 0) { OUTPUT_LOG("warning: LOD file %s does not contain any lod mesh references\n", filename.c_str()); return E_FAIL; } } } else { OUTPUT_LOG("failed loading mesh xml file: %s\n", filename.c_str()); return E_FAIL; } } else { CreateMeshLODLevel(0.f, filename); } } try { // preload file data to memory in the IO thread. std::vector<MeshLOD> & pMeshLODs = m_MeshLODs.size() > 0 ? m_MeshLODs : m_asset->m_MeshLODs; for (auto iCur = pMeshLODs.begin(); iCur != pMeshLODs.end(); ++iCur) { if ( ! (iCur->m_pParaXMesh) ) { CParaFile myFile(iCur->m_sMeshFileName.c_str()); if (myFile.isEof()) { OUTPUT_LOG("warning: ParaX model file not found %s\n", iCur->m_sMeshFileName.c_str()); return E_FAIL; } std::string sExt = CParaFile::GetFileExtension(iCur->m_sMeshFileName); StringHelper::make_lower(sExt); if (sExt == "bmax") { // block max model. BMaxParser p(myFile.getBuffer(), myFile.getSize()); iCur->m_pParaXMesh = p.ParseParaXModel(); auto pParaXMesh = iCur->m_pParaXMesh; #ifdef ENABLE_BMAX_AUTO_LOD if (m_MeshLODs.size() == 1) { // each LOD at least cut triangle count in half and no bigger than a given count. // by default, generate lod in range 30, 60, 90, 120 meters; // TODO: currently it is hard-coded, shall we read LOD settings from bmax file, so that users // have find-control on the settings. struct LODSetting { int nMaxTriangleCount; float fMaxDistance; }; const LODSetting nLodsMaxTriangleCounts[] = { {2000, 60.f}, {500, 90.f}, {100, 120.f} }; // from second lod for (int i = 0; pParaXMesh && i < sizeof(nLodsMaxTriangleCounts)/sizeof(LODSetting); i++) { if ((int)pParaXMesh->GetPolyCount() >= nLodsMaxTriangleCounts[i].nMaxTriangleCount) { MeshLOD lod; lod.m_pParaXMesh = p.ParseParaXModel((std::min)(nLodsMaxTriangleCounts[i].nMaxTriangleCount, (int)(pParaXMesh->GetPolyCount() / 2) - 4)); lod.m_fromDepthSquared = Math::Sqr(nLodsMaxTriangleCounts[i].fMaxDistance); if (lod.m_pParaXMesh) { if (pMeshLODs.size() == 1) { iCur->m_fromDepthSquared = Math::Sqr(nLodsMaxTriangleCounts[0].fMaxDistance*0.5f); } pParaXMesh = lod.m_pParaXMesh; pMeshLODs.push_back(lod); iCur = pMeshLODs.end() - 1; } } } } #endif } #ifdef SUPPORT_FBX_MODEL_FILE else if (sExt == "fbx") { // static or animated fbx model FBXParser parser(iCur->m_sMeshFileName); iCur->m_pParaXMesh = parser.ParseParaXModel(myFile.getBuffer(), myFile.getSize()); } #endif else { CParaXSerializer serializer; #if defined(USE_DIRECTX_RENDERER) && !defined(_DEBUG) ParaXParser parser(myFile, CAsyncLoader::GetSingleton().GetFileParser()); iCur->m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile, parser); #else iCur->m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile); #endif } if (iCur->m_pParaXMesh == 0) { // lod.m_pParaXMesh = new CParaXModel(ParaXHeaderDef()); OUTPUT_LOG("warning: cannot load ParaX model file %s\n", iCur->m_sMeshFileName.c_str()); return E_FAIL; } if (!iCur->m_pParaXMesh->IsValid()) { return E_FAIL; } else { m_nTechniqueHandle = iCur->m_pParaXMesh->IsBmaxModel() ? TECH_BMAX_MODEL : TECH_CHARACTER; } } } } catch (...) { OUTPUT_LOG("warning: failed initialize ParaX model %s\n", m_asset->GetLocalFileName().c_str()); return E_FAIL; } return S_OK; }
HRESULT ParaEngine::CParaXProcessor::CopyToResource() { if (m_asset.get() == 0) return E_FAIL; if (m_asset->m_MeshLODs.size() == 0) { string filename = m_asset->GetLocalFileName(); bool bLoadHeaderFromXFile = true; bool bSingleLOD = true; bool bIsXML = (CParaFile::GetFileExtension(filename) == "xml"); string sParentDirectory = CParaFile::GetParentDirectoryFromPath(filename); // check in manifest AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(filename); if (pEntry) { if (pEntry->DoesFileExist()) { filename = pEntry->GetLocalFileName(); } else { m_pAssetFileEntry = pEntry; return E_PENDING; } } if (bIsXML) { CParaMeshXMLFile file; if (file.LoadFromFile(filename, sParentDirectory)) { if (file.GetType() == CParaMeshXMLFile::TYPE_MESH_LOD) { int i; // check if all sub files are available locally. for (i = 0; i < file.GetSubMeshCount(); ++i) { CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i); AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(pSubLODMesh->m_sFileName); if (pEntry) { if (pEntry->DoesFileExist()) { pSubLODMesh->m_sFileName = pEntry->GetLocalFileName(); } else { m_pAssetFileEntry = pEntry; return E_PENDING; } } } if (file.m_bHasBoundingBox) { } for (i = 0; i < file.GetSubMeshCount(); ++i) { CParaMeshXMLFile::CSubMesh* pSubLODMesh = file.GetSubMesh(i); CreateMeshLODLevel(pSubLODMesh->m_fToCameraDist, pSubLODMesh->m_sFileName); } if (file.GetSubMeshCount() == 0) { OUTPUT_LOG("warning: LOD file %s does not contain any lod mesh references\n", filename.c_str()); return E_FAIL; } } } else { OUTPUT_LOG("failed loading mesh xml file: %s\n", filename.c_str()); return E_FAIL; } } else { CreateMeshLODLevel(0.f, filename); } } try { // preload file data to memory in the IO thread. std::vector<MeshLOD> & pMeshLODs = m_MeshLODs.size() > 0 ? m_MeshLODs : m_asset->m_MeshLODs; std::vector<MeshLOD>::iterator iCur, iEnd = pMeshLODs.end(); for (iCur = pMeshLODs.begin(); iCur != iEnd; ++iCur) { MeshLOD& lod = (*iCur); if (lod.m_pParaXMesh == 0) { CParaFile myFile(lod.m_sMeshFileName.c_str()); if (myFile.isEof()) { OUTPUT_LOG("warning: ParaX model file not found %s\n", lod.m_sMeshFileName.c_str()); return E_FAIL; } std::string sExt = CParaFile::GetFileExtension(lod.m_sMeshFileName); StringHelper::make_lower(sExt); if (sExt == "bmax") { // block max model. BMaxParser p(myFile.getBuffer(), myFile.getSize()); lod.m_pParaXMesh = p.ParseParaXModel(); } #ifdef SUPPORT_FBX_MODEL_FILE else if (sExt == "fbx") { // static or animated fbx model FBXParser parser(lod.m_sMeshFileName); lod.m_pParaXMesh = parser.ParseParaXModel(myFile.getBuffer(), myFile.getSize()); } #endif else { CParaXSerializer serializer; #ifdef USE_DIRECTX_RENDERER ParaXParser parser(myFile, CAsyncLoader::GetSingleton().GetFileParser()); lod.m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile, parser); #elif defined(USE_OPENGL_RENDERER) lod.m_pParaXMesh = (CParaXModel*)serializer.LoadParaXMesh(myFile); #endif } if (lod.m_pParaXMesh == 0) { // lod.m_pParaXMesh = new CParaXModel(ParaXHeaderDef()); OUTPUT_LOG("warning: cannot load ParaX model file %s\n", lod.m_sMeshFileName.c_str()); return E_FAIL; } if (!lod.m_pParaXMesh->IsValid()) { return E_FAIL; } else { m_nTechniqueHandle = lod.m_pParaXMesh->IsBmaxModel() ? TECH_BMAX_MODEL : TECH_CHARACTER; } } } } catch (...) { OUTPUT_LOG("warning: failed initialize ParaX model %s\n", m_asset->GetLocalFileName().c_str()); return E_FAIL; } return S_OK; }