LifePlay-Revival/Source/LifePlayEditorTools/LPDumpComponentsCommandlet.cpp
2026-09-30 11:33:05 +02:00

155 lines
5 KiB
C++

// Voir LPDumpComponentsCommandlet.h
#include "LPDumpComponentsCommandlet.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "Components/ActorComponent.h"
#include "Engine/Blueprint.h"
#include "Engine/SCS_Node.h"
#include "Engine/SimpleConstructionScript.h"
#include "Engine/Level.h"
#include "Engine/World.h"
#include "GameFramework/Actor.h"
DEFINE_LOG_CATEGORY_STATIC(LogLPCompDump, Log, All);
namespace
{
void DumpObject(const UObject* Obj, bool bAll)
{
const UObject* Defaults = Obj->GetClass()->GetDefaultObject();
for (TFieldIterator<FProperty> It(Obj->GetClass()); It; ++It)
{
const FProperty* Prop = *It;
if (Prop->IsA<FMulticastDelegateProperty>() || Prop->IsA<FDelegateProperty>())
{
continue;
}
const bool bSame = Prop->Identical_InContainer(Obj, Defaults, 0, PPF_None);
if (bSame && !bAll)
{
continue;
}
FString Value;
Prop->ExportText_InContainer(0, Value, Obj, bSame ? nullptr : Defaults, const_cast<UObject*>(Obj), PPF_None);
if (Value.Len() > 4000)
{
Value = Value.Left(4000) + TEXT("...");
}
UE_LOG(LogLPCompDump, Warning, TEXT(" %s%s = %s"), bSame ? TEXT("(defaut) ") : TEXT(""), *Prop->GetName(), *Value);
}
}
}
ULPDumpComponentsCommandlet::ULPDumpComponentsCommandlet()
{
IsClient = false;
IsServer = false;
IsEditor = true;
LogToConsole = true;
}
int32 ULPDumpComponentsCommandlet::Main(const FString& Params)
{
TArray<FString> Tokens, Switches;
TMap<FString, FString> ParamsMap;
ParseCommandLine(*Params, Tokens, Switches, ParamsMap);
const FString WantedBP = ParamsMap.FindRef(TEXT("BP"));
const FString WantedMap = ParamsMap.FindRef(TEXT("Map"));
const FString Filter = ParamsMap.FindRef(TEXT("Filter"));
const bool bAll = Switches.Contains(TEXT("All"));
if (WantedBP.IsEmpty() && WantedMap.IsEmpty())
{
UE_LOG(LogLPCompDump, Error, TEXT("Usage : -BP=<Blueprint> [-All] | -Map=<chemin /Game/...> -Filter=<texte> [-All]"));
return 1;
}
// -Map : acteurs d'une carte dont la classe ou le nom contient le filtre.
if (!WantedMap.IsEmpty())
{
UPackage* Package = LoadPackage(nullptr, *WantedMap, LOAD_None);
const UWorld* World = Package ? UWorld::FindWorldInPackage(Package) : nullptr;
if (!World || !World->PersistentLevel)
{
UE_LOG(LogLPCompDump, Error, TEXT("Carte '%s' introuvable."), *WantedMap);
return 1;
}
UE_LOG(LogLPCompDump, Warning, TEXT("=== %s : acteurs '%s' ==="), *WantedMap, *Filter);
for (const AActor* Actor : World->PersistentLevel->Actors)
{
if (!Actor || (!Filter.IsEmpty() && !Actor->GetClass()->GetName().Contains(Filter) && !Actor->GetName().Contains(Filter)))
{
continue;
}
UE_LOG(LogLPCompDump, Warning, TEXT(" [acteur] %s (%s) a %s"), *Actor->GetName(), *Actor->GetClass()->GetName(),
*Actor->GetActorLocation().ToString());
DumpObject(Actor, bAll);
for (const UActorComponent* Comp : Actor->GetComponents())
{
if (Comp)
{
UE_LOG(LogLPCompDump, Warning, TEXT(" [composant] %s (%s)"), *Comp->GetName(), *Comp->GetClass()->GetName());
DumpObject(Comp, bAll);
}
}
}
return 0;
}
FAssetRegistryModule& AssetRegistryModule =
FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
AssetRegistryModule.Get().SearchAllAssets(true);
TArray<FAssetData> Assets;
AssetRegistryModule.Get().GetAssetsByClass(UBlueprint::StaticClass()->GetClassPathName(), Assets, true);
const UBlueprint* Target = nullptr;
for (const FAssetData& AssetData : Assets)
{
if (AssetData.PackageName.ToString().StartsWith(TEXT("/Game/")) && AssetData.AssetName.ToString() == WantedBP)
{
Target = Cast<UBlueprint>(AssetData.GetAsset());
break;
}
}
if (!Target || !Target->GeneratedClass)
{
UE_LOG(LogLPCompDump, Error, TEXT("Blueprint '%s' introuvable sous /Game."), *WantedBP);
return 1;
}
UE_LOG(LogLPCompDump, Warning, TEXT("=== %s ==="), *Target->GetPathName());
const UObject* CDO = Target->GeneratedClass->GetDefaultObject();
UE_LOG(LogLPCompDump, Warning, TEXT(" [CDO] %s"), *CDO->GetClass()->GetName());
DumpObject(CDO, false);
// Composants ajoutes dans l'editeur de Blueprint.
if (Target->SimpleConstructionScript)
{
for (const USCS_Node* Node : Target->SimpleConstructionScript->GetAllNodes())
{
if (Node && Node->ComponentTemplate)
{
UE_LOG(LogLPCompDump, Warning, TEXT(" [SCS] %s (%s) parent=%s"), *Node->GetVariableName().ToString(),
*Node->ComponentTemplate->GetClass()->GetName(), *Node->ParentComponentOrVariableName.ToString());
DumpObject(Node->ComponentTemplate, bAll);
}
}
}
// Composants natifs (heritage C++) portes par le CDO.
if (const AActor* Actor = Cast<AActor>(CDO))
{
for (const UActorComponent* Comp : Actor->GetComponents())
{
if (Comp)
{
UE_LOG(LogLPCompDump, Warning, TEXT(" [natif] %s (%s)"), *Comp->GetName(), *Comp->GetClass()->GetName());
DumpObject(Comp, bAll);
}
}
}
return 0;
}