static byte *FindBioTexture(const UTexture *Tex) { int needSize = Tex->CachedBulkDataSize & 0xFFFFFFFF; #if DEBUG_BIO_BULK appPrintf("Search for ... %s (size=%X)\n", Tex->Name, needSize); #endif BioReadBulkCatalog(); for (int i = 0; i < bioCatalog.Num(); i++) { BioBulkCatalog &Cat = bioCatalog[i]; for (int j = 0; j < Cat.Files.Num(); j++) { const BioBulkCatalogFile &File = Cat.Files[j]; for (int k = 0; k < File.Items.Num(); k++) { const BioBulkCatalogItem &Item = File.Items[k]; if (!strcmp(Tex->Name, Item.ObjectName)) { if (abs(needSize - Item.DataSize) > 0x4000) // differs in 16k { #if DEBUG_BIO_BULK appPrintf("... Found %s in %s with wrong BulkDataSize %X (need %X)\n", Tex->Name, *File.Filename, Item.DataSize, needSize); #endif continue; } #if DEBUG_BIO_BULK appPrintf("... Found %s in %s at %X size %X (%dx%d fmt=%d bpp=%g strip:%d mips:%d)\n", Tex->Name, *File.Filename, Item.DataOffset, Item.DataSize, Tex->USize, Tex->VSize, Tex->Format, (float)Item.DataSize / (Tex->USize * Tex->VSize), Tex->HasBeenStripped, Tex->StrippedNumMips); #endif // found const CGameFileInfo *bulkFile = appFindGameFile(File.Filename); if (!bulkFile) { // no bulk file appPrintf("Decompressing %s: %s is missing\n", Tex->Name, *File.Filename); return NULL; } appPrintf("Reading %s mip level %d (%dx%d) from %s\n", Tex->Name, 0, Tex->USize, Tex->VSize, bulkFile->RelativeName); FArchive *Reader = appCreateFileReader(bulkFile); Reader->Seek(Item.DataOffset); byte *buf = (byte*)appMalloc(max(Item.DataSize, needSize)); Reader->Serialize(buf, Item.DataSize); delete Reader; return buf; } } } } #if DEBUG_BIO_BULK appPrintf("... Bulk for %s was not found\n", Tex->Name); #endif return NULL; }
//?? TODO: may be pass "Ext" here void appFindGameFiles(const char *Filename, TArray<const CGameFileInfo*>& Files) { guard(appFindGameFiles); if (!appContainsWildcard(Filename)) { const CGameFileInfo* File = appFindGameFile(Filename); if (File) Files.Add(File); return; } // here we're working with wildcard and should iterate over all files char buf[MAX_PACKAGE_PATH]; appStrncpyz(buf, Filename, ARRAY_COUNT(buf)); // replace backslashes bool containsPath = false; for (char* s = buf; *s; s++) { char c = *s; if (c == '\\') { *s = '/'; containsPath = true; } else if (c == '/') { containsPath = true; } } FindPackageWildcardData findData; findData.WildcardContainsPath = containsPath; findData.Wildcard = buf; appEnumGameFiles(FindPackageWildcardCallback, findData); CopyArray(Files, findData.FoundFiles); unguardf("wildcard=%s", Filename); }
void CSkelMeshViewer::FindUE4Animations() { #if UNREAL4 guard(CSkelMeshViewer::FindUE4Animations); if (!bIsUE4Mesh) return; if (!Skeleton) { appPrintf("No Skeleton object attached to the mesh, doing nothing\n"); return; } // Find all packages TArray<const CGameFileInfo*> PackageInfos; appEnumGameFiles<TArray<const CGameFileInfo*> >( // won't compile with lambda without explicitly providing template argument [](const CGameFileInfo* file, TArray<const CGameFileInfo*>& param) -> bool { param.Add(file); return true; }, PackageInfos); UIProgressDialog progress; progress.Show("Finding animations"); progress.SetDescription("Scanning package"); // Perform full scan to be able to locate AnimSequence objects if (!ScanContent(PackageInfos, &progress)) { appPrintf("Interrupted by user\n"); return; } // Find potential uasset files with animations TArray<UnPackage*> packagesToLoad; packagesToLoad.Empty(256); const char* lookupSkeletonName = Skeleton->Name; for (int i = 0; i < PackageInfos.Num(); i++) { UnPackage* package = PackageInfos[i]->Package; bool found = false; for (int importIndex = 0; importIndex < package->Summary.ImportCount; importIndex++) { FObjectImport& imp = package->GetImport(importIndex); const char* ObjectClass = *imp.ClassName; const char* ObjectName = *imp.ObjectName; if (!stricmp(ObjectClass, "Skeleton") && !stricmp(ObjectName, lookupSkeletonName)) { // This uasset refers to the Skeleton object with the same name, check if this // is an exactly the same Skeleton object as we're using const char* referencedFilename = package->GetObjectPackageName(imp.PackageIndex); const CGameFileInfo* referencedFile = appFindGameFile(referencedFilename); if (!stricmp(Skeleton->Package->Filename, *referencedFile->GetRelativeName())) { found = true; break; } } } if (!found) continue; // this package doesn't use our Skeleton // Now, if this package has animation sequence - enqueue it for loading if (PackageInfos[i]->NumAnimations) { packagesToLoad.Add(package); } } // Sort packages by name for easier navigation after loading packagesToLoad.Sort([](UnPackage* const& a, UnPackage* const& b) -> int { return stricmp(a->Name, b->Name); }); // Load queued packages progress.SetDescription("Loading animations"); for (int i = 0; i < packagesToLoad.Num(); i++) { guard(Load); UnPackage* package = packagesToLoad[i]; if (!progress.Progress(package->Filename, i, packagesToLoad.Num())) break; LoadWholePackage(package); unguardf("%d/%d", i, packagesToLoad.Num()); } unguard; #endif // UNREAL4 }