LifePlay-Revival/Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet.cpp
2026-10-01 22:08:14 +02:00

159 lines
5.2 KiB
C++

// Portage UE 5.5 - voir LPFixSceneCaptureCommandlet.h
#include "LPFixSceneCaptureCommandlet.h"
#include "Components/SceneCaptureComponent2D.h"
#include "Engine/Level.h"
#include "Engine/SceneCapture2D.h"
#include "Engine/World.h"
#include "Misc/PackageName.h"
#include "UObject/Package.h"
#include "UObject/SavePackage.h"
DEFINE_LOG_CATEGORY_STATIC(LogLPFixSceneCapture, Log, All);
namespace
{
AActor* FindActorByLabelOrName(ULevel* Level, const FString& Name)
{
for (AActor* Actor : Level->Actors)
{
if (Actor && (Actor->GetActorLabel() == Name || Actor->GetName() == Name))
{
return Actor;
}
}
return nullptr;
}
}
ULPFixSceneCaptureCommandlet::ULPFixSceneCaptureCommandlet()
{
IsClient = false;
IsServer = false;
IsEditor = true;
LogToConsole = true;
}
int32 ULPFixSceneCaptureCommandlet::Main(const FString& Params)
{
TArray<FString> Tokens, Switches;
TMap<FString, FString> ParamsMap;
ParseCommandLine(*Params, Tokens, Switches, ParamsMap);
const bool bDryRun = Switches.Contains(TEXT("DryRun"));
const FString MapPath = ParamsMap.FindRef(TEXT("Map"));
const FString ActorName = ParamsMap.FindRef(TEXT("Actor"));
const FString FromName = ParamsMap.FindRef(TEXT("From"));
FVector Offset = FVector::ZeroVector;
{
TArray<FString> Parts;
ParamsMap.FindRef(TEXT("Offset")).ParseIntoArray(Parts, TEXT(","), true);
if (Parts.Num() == 3)
{
Offset = FVector(FCString::Atod(*Parts[0]), FCString::Atod(*Parts[1]), FCString::Atod(*Parts[2]));
}
}
if (MapPath.IsEmpty() || ActorName.IsEmpty() || FromName.IsEmpty())
{
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Usage : -Map=/Game/Scenes/X -Actor=<capture> -From=<acteur de reference> [-Offset=x,y,z] [-DryRun]"));
return 1;
}
const FString WorldPath = MapPath + TEXT(".") + FPackageName::GetShortName(MapPath);
UWorld* World = LoadObject<UWorld>(nullptr, *WorldPath);
if (!World || !World->PersistentLevel)
{
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Carte introuvable : %s"), *WorldPath);
return 1;
}
World->AddToRoot();
ASceneCapture2D* Capture = Cast<ASceneCapture2D>(FindActorByLabelOrName(World->PersistentLevel, ActorName));
AActor* From = FindActorByLabelOrName(World->PersistentLevel, FromName);
if (!Capture || !From || !From->GetRootComponent())
{
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Acteur introuvable : %s (capture) ou %s (reference, avec racine)"), *ActorName, *FromName);
World->RemoveFromRoot();
return 1;
}
USceneCaptureComponent2D* CaptureComp = Capture->GetCaptureComponent2D();
USceneComponent* NewRoot = nullptr;
for (UActorComponent* Comp : Capture->GetComponents())
{
USceneComponent* SceneComp = Cast<USceneComponent>(Comp);
if (SceneComp && SceneComp != CaptureComp && SceneComp->GetClass() == USceneComponent::StaticClass())
{
NewRoot = SceneComp;
break;
}
}
if (!NewRoot)
{
NewRoot = CaptureComp;
}
const FTransform FromTransform = From->GetRootComponent()->GetRelativeTransform();
const FTransform Target(FromTransform.GetRotation(), FromTransform.GetLocation() + Offset, FVector::OneVector);
UE_LOG(LogLPFixSceneCapture, Warning, TEXT("=== %s : racine %s -> %s, cible %s (= %s + %s)%s ==="),
*Capture->GetActorLabel(), *GetNameSafe(Capture->GetRootComponent()), *GetNameSafe(NewRoot),
*Target.ToString(), *FromName, *Offset.ToString(), bDryRun ? TEXT(" [DRY RUN]") : TEXT(""));
if (bDryRun)
{
World->RemoveFromRoot();
return 0;
}
Capture->Modify();
Capture->SetRootComponent(NewRoot);
if (CaptureComp && CaptureComp != NewRoot)
{
CaptureComp->AttachToComponent(NewRoot, FAttachmentTransformRules::KeepRelativeTransform);
CaptureComp->SetRelativeTransform(FTransform::Identity);
}
NewRoot->SetRelativeTransform(Target);
NewRoot->UpdateComponentToWorld();
if (CaptureComp && CaptureComp != NewRoot)
{
CaptureComp->UpdateComponentToWorld();
}
// Verification : racine, rattachement, position monde de la capture.
int32 Errors = 0;
if (Capture->GetRootComponent() != NewRoot) { ++Errors; UE_LOG(LogLPFixSceneCapture, Error, TEXT(" racine non affectee")); }
if (CaptureComp && CaptureComp != NewRoot && CaptureComp->GetAttachParent() != NewRoot) { ++Errors; UE_LOG(LogLPFixSceneCapture, Error, TEXT(" capture non rattachee")); }
const FTransform Final = CaptureComp ? CaptureComp->GetComponentTransform() : NewRoot->GetComponentTransform();
if (!Final.Equals(Target, 0.01))
{
++Errors;
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" position finale %s differente de la cible %s"), *Final.ToString(), *Target.ToString());
}
UE_LOG(LogLPFixSceneCapture, Warning, TEXT(" capture : position monde %s"), *Final.ToString());
int32 Result = 0;
if (Errors == 0)
{
UPackage* Package = World->GetOutermost();
const FString Filename = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetMapPackageExtension());
FSavePackageArgs SaveArgs;
SaveArgs.TopLevelFlags = RF_Standalone;
SaveArgs.Error = GWarn;
if (UPackage::SavePackage(Package, World, *Filename, SaveArgs))
{
UE_LOG(LogLPFixSceneCapture, Warning, TEXT(" -> carte sauvegardee"));
}
else
{
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" ECHEC de sauvegarde"));
Result = 1;
}
}
else
{
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" %d ecart(s) : carte NON sauvegardee"), Errors);
Result = 1;
}
World->RemoveFromRoot();
return Result;
}