/** * Debug spew for components * @param Object object to dump component spew for */ void DumpComponents(UObject *Object) { for ( FObjectIterator It; It; ++It ) { It->UnMark(EObjectMark(OBJECTMARK_TagImp | OBJECTMARK_TagExp)); } if (FPlatformMisc::IsDebuggerPresent() ) { // if we have a debugger attached, the watch window won't be able to display the full output if we attempt to log it as a single string // so pass in GLog instead so that each line is sent separately; this causes the output to have an extra line break between each log statement, // but at least we'll be able to see the full output in the debugger's watch window UE_LOG(LogExporter, Log, TEXT("Components for '%s':"), *Object->GetFullName()); ExportProperties( NULL, *GLog, Object->GetClass(), (uint8*)Object, 0, NULL, NULL, Object, PPF_SubobjectsOnly ); UE_LOG(LogExporter, Log, TEXT("<--- DONE!")); } else { FStringOutputDevice Output; Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName()); ExportProperties( NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly ); Output.Logf(TEXT("<--- DONE!\r\n")); UE_LOG(LogExporter, Log, TEXT("%s"), *Output); } }
FString DumpComponentsToString(UObject *Object) { UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); FStringOutputDevice Output; Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName()); ExportProperties(NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly); Output.Logf(TEXT("<--- DONE!\r\n")); return Output; }
void LogIncludeCount(const TArray<FString>& IncludesInPCH, const TMap<FString, int32>& IncludeHeaderCount, int32 FileCount, float IncludePercentageThreshold) { for (const auto& FilenameAbsolutePath : IncludesInPCH) { auto IncludeCount = GetIncludeCount(IncludeHeaderCount, FilenameAbsolutePath); auto IncludePercentage = static_cast<float>(IncludeCount) / static_cast<float>(FileCount); if (IncludePercentage < IncludePercentageThreshold) { OutputFileContents.Logf(TEXT("%s %i(%f%%) with threshold %f%%"), *FilenameAbsolutePath, IncludeCount, IncludePercentage, IncludePercentageThreshold); } } }
int AnalyzePCHFile(const FString& CmdLine) { auto IncludePercentageThreshold = ParseUsageThreshold(*CmdLine); auto IncludeSearchPaths = ParseIncludeSearchPaths(*CmdLine); FString IncludesDirectory; FParse::Value(*CmdLine, TEXT("-HeaderDataPath="), IncludesDirectory); int32 FileCount = 0; TMap<FString, int32> IncludeHeaderCount; GatherModuleHeaderData(*IncludesDirectory, FileCount, IncludeHeaderCount); // Open PCH file FString PCHFilePath; FParse::Value(*CmdLine, TEXT("-PCHFile="), PCHFilePath); TArray<FString> IncludesInPCH = GetIncludesInPCH(PCHFilePath, IncludeSearchPaths); OutputFileContents.Logf(TEXT("Remove the following #includes from %s"), *PCHFilePath); LogIncludeCount(IncludesInPCH, IncludeHeaderCount, FileCount, IncludePercentageThreshold); OutputFileContents.Logf(TEXT("Add the following #includes to %s"), *PCHFilePath); for (auto KVP : IncludeHeaderCount) { const auto& Filename = KVP.Key; const auto& HeaderIncludeCount = KVP.Value; auto IncludePercentage = static_cast<float>(HeaderIncludeCount) / static_cast<float>(FileCount); if (IncludePercentage > IncludePercentageThreshold) { OutputFileContents.Logf(TEXT("%s (%i/%i)%f%%"), *Filename, HeaderIncludeCount, FileCount, IncludePercentage); } } return 0; }
bool UDiffAssetsCommandlet::ExportFile(const FString& Filename, const TArray<UObject *>& LoadedObjects) { FString Extension = TEXT("t3d"); FStringOutputDevice Buffer; const FExportObjectInnerContext Context; for (int32 Index = 0; Index < LoadedObjects.Num(); Index++) { UExporter* Exporter = UExporter::FindExporter( LoadedObjects[Index], *Extension ); if (!Exporter) { UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Could not find exporter.")); return false; } UExporter::ExportToOutputDevice( &Context, LoadedObjects[Index], Exporter, Buffer, *Extension, 0, PPF_ExportsNotFullyQualified, false ); TMap<FString,FString> NativePropertyValues; if ( LoadedObjects[Index]->GetNativePropertyValues(NativePropertyValues) && NativePropertyValues.Num()) { int32 LargestKey = 0; for ( TMap<FString,FString>::TIterator It(NativePropertyValues); It; ++It ) { LargestKey = FMath::Max(LargestKey, It.Key().Len()); } for ( TMap<FString,FString>::TIterator It(NativePropertyValues); It; ++It ) { Buffer.Logf(TEXT(" %s=%s"), *It.Key().RightPad(LargestKey), *It.Value()); } } } if (!Buffer.Len()) { UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("No text was exported!")); return false; } if( !FFileHelper::SaveStringToFile( Buffer, *Filename ) ) { UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Could not write %s"), *Filename); return false; } return true; }