// Voir LPDumpAssetsCommandlet.h #include "LPDumpAssetsCommandlet.h" #include "EdGraph/EdGraphNode.h" #include "EdGraph/EdGraphPin.h" #include "LPAssetListUtils.h" #include "Misc/EngineVersionComparison.h" #include "Misc/FileHelper.h" #include "UObject/Package.h" #include "UObject/UObjectHash.h" DEFINE_LOG_CATEGORY_STATIC(LogLPDumpAssets, Log, All); namespace { void DumpProperties(const UObject* Obj, TArray& Out) { const UObject* Defaults = Obj->GetClass()->GetDefaultObject(); if (Obj == Defaults) { return; } for (TFieldIterator It(Obj->GetClass()); It; ++It) { const FProperty* Prop = *It; if (Prop->HasAnyPropertyFlags(CPF_Transient) || Prop->IsA() || Prop->IsA()) { continue; } if (Prop->Identical_InContainer(Obj, Defaults, 0, PPF_None)) { continue; } FString Value; Prop->ExportText_InContainer(0, Value, Obj, Defaults, const_cast(Obj), PPF_None); Out.Add(FString::Printf(TEXT(" %s = %s"), *Prop->GetName(), *Value)); } } void DumpPins(const UEdGraphNode* Node, TArray& Out) { for (const UEdGraphPin* Pin : Node->Pins) { if (!Pin) { continue; } TArray Links; for (const UEdGraphPin* L : Pin->LinkedTo) { Links.Add(FString::Printf(TEXT("%s.%s"), L && L->GetOwningNode() ? *L->GetOwningNode()->GetName() : TEXT("?"), L ? *L->PinName.ToString() : TEXT("?"))); } Links.Sort(); Out.Add(FString::Printf(TEXT(" pin %s%s [%s] defaut='%s' objet=%s texte='%s' -> %s"), Pin->bOrphanedPin ? TEXT("[X] ") : TEXT(""), *Pin->PinName.ToString(), *Pin->PinType.PinCategory.ToString(), *Pin->DefaultValue, Pin->DefaultObject ? *Pin->DefaultObject->GetPathName() : TEXT("None"), *Pin->DefaultTextValue.ToString(), *FString::Join(Links, TEXT(", ")))); } } } ULPDumpAssetsCommandlet::ULPDumpAssetsCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPDumpAssetsCommandlet::Main(const FString& Params) { TArray Tokens, Switches; TMap ParamsMap; ParseCommandLine(*Params, Tokens, Switches, ParamsMap); const FString OutFile = ParamsMap.FindRef(TEXT("Out")); const TArray Packages = LPAssetList::Resolve(ParamsMap); if (OutFile.IsEmpty() || Packages.Num() == 0) { UE_LOG(LogLPDumpAssets, Error, TEXT("Usage : (-List= | -Dirs=/Game/A,/Game/B) -Out=")); return 1; } // Tout charger d'abord : les dependances entre paquets de la liste sont alors resolues // de la meme facon a chaque photographie, quel que soit l'ordre. TArray Loaded; int32 Failures = 0; for (const FString& Name : Packages) { UPackage* Package = LoadPackage(nullptr, *Name, LOAD_None); if (!Package) { ++Failures; UE_LOG(LogLPDumpAssets, Error, TEXT("Chargement impossible : %s"), *Name); } Loaded.Add(Package); } TArray Out; for (int32 i = 0; i < Packages.Num(); ++i) { Out.Add(FString::Printf(TEXT("##### %s"), *Packages[i])); if (!Loaded[i]) { Out.Add(TEXT(" (chargement impossible)")); continue; } TArray Objects; #if UE_VERSION_OLDER_THAN(5, 8, 0) GetObjectsWithPackage(Loaded[i], Objects, true); #else // 5.8 : surcharge booleenne depreciee (UObjectHash.h:195-199, true -> IncludeNestedObjects) ; enum l. 193. GetObjectsWithPackage(Loaded[i], Objects, EGetObjectsFlags::IncludeNestedObjects); #endif Objects.Sort([](const UObject& A, const UObject& B) { return A.GetPathName() < B.GetPathName(); }); for (const UObject* Obj : Objects) { Out.Add(FString::Printf(TEXT(" %s [%s]"), *Obj->GetPathName(Loaded[i]), *Obj->GetClass()->GetName())); DumpProperties(Obj, Out); if (const UEdGraphNode* Node = Cast(Obj)) { DumpPins(Node, Out); } } } FFileHelper::SaveStringArrayToFile(Out, *OutFile, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); UE_LOG(LogLPDumpAssets, Warning, TEXT("=== %d paquet(s), %d echec(s) de chargement, %d ligne(s) -> %s ==="), Packages.Num(), Failures, Out.Num(), *OutFile); return Failures > 0 ? 1 : 0; }