// Portage UE 5.5 - voir LPConvertAtmosphericFogCommandlet.h #include "LPConvertAtmosphericFogCommandlet.h" #include "Atmosphere/AtmosphericFog.h" #include "Atmosphere/AtmosphericFogComponent.h" #include "Components/SkyAtmosphereComponent.h" #include "Engine/Level.h" #include "Engine/World.h" #include "Misc/PackageName.h" #include "UObject/Package.h" #include "UObject/SavePackage.h" #include "UObject/UnrealType.h" DEFINE_LOG_CATEGORY_STATIC(LogLPConvertAtmo, Log, All); namespace { FString ExportProp(const FProperty* Prop, const UObject* Obj) { FString Text; Prop->ExportTextItem_Direct(Text, Prop->ContainerPtrToValuePtr(Obj), nullptr, nullptr, PPF_None); return Text; } } ULPConvertAtmosphericFogCommandlet::ULPConvertAtmosphericFogCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPConvertAtmosphericFogCommandlet::Main(const FString& Params) { TArray Tokens, Switches; TMap ParamsMap; ParseCommandLine(*Params, Tokens, Switches, ParamsMap); const bool bDryRun = Switches.Contains(TEXT("DryRun")); const FString MapPath = ParamsMap.FindRef(TEXT("Map")); if (MapPath.IsEmpty()) { UE_LOG(LogLPConvertAtmo, Error, TEXT("Usage : -Map=/Game/Scenes/X [-DryRun]")); return 1; } const FString WorldPath = MapPath + TEXT(".") + FPackageName::GetShortName(MapPath); UWorld* World = LoadObject(nullptr, *WorldPath); if (!World || !World->PersistentLevel) { UE_LOG(LogLPConvertAtmo, Error, TEXT("Carte introuvable : %s"), *WorldPath); return 1; } World->AddToRoot(); if (!World->bIsWorldInitialized) { World->InitWorld(UWorld::InitializationValues().AllowAudioPlayback(false).CreatePhysicsScene(false).CreateNavigation(false).CreateAISystem(false).ShouldSimulatePhysics(false).EnableTraceCollision(false).SetTransactional(false).CreateFXSystem(false)); } UE_LOG(LogLPConvertAtmo, Warning, TEXT("=== AtmosphericFog -> SkyAtmosphere : %s%s ==="), *MapPath, bDryRun ? TEXT(" [DRY RUN]") : TEXT("")); PRAGMA_DISABLE_DEPRECATION_WARNINGS TArray Fogs; for (AActor* Actor : World->PersistentLevel->Actors) { if (AAtmosphericFog* Fog = Cast(Actor)) { Fogs.Add(Fog); } } int32 Mismatches = 0; int32 Converted = 0; for (AAtmosphericFog* Fog : Fogs) { UAtmosphericFogComponent* OldComp = Fog->GetAtmosphericFogComponent(); UE_LOG(LogLPConvertAtmo, Warning, TEXT(" %s (%s), transformation %s"), *Fog->GetName(), *Fog->GetActorLabel(), *Fog->GetActorTransform().ToString()); if (!OldComp) { ++Mismatches; UE_LOG(LogLPConvertAtmo, Error, TEXT(" composant absent")); continue; } if (bDryRun) { for (TFieldIterator It(USkyAtmosphereComponent::StaticClass(), EFieldIteratorFlags::ExcludeSuper); It; ++It) { UE_LOG(LogLPConvertAtmo, Display, TEXT(" %s = %s"), *It->GetName(), *ExportProp(*It, OldComp)); } continue; } FActorSpawnParameters SpawnParams; SpawnParams.OverrideLevel = World->PersistentLevel; SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; ASkyAtmosphere* Sky = World->SpawnActor(ASkyAtmosphere::StaticClass(), Fog->GetActorTransform(), SpawnParams); USkyAtmosphereComponent* NewComp = Sky ? Sky->GetComponent() : nullptr; if (!NewComp) { ++Mismatches; UE_LOG(LogLPConvertAtmo, Error, TEXT(" creation du SkyAtmosphere impossible")); continue; } // Valeurs effectives de toutes les proprietes declarees par USkyAtmosphereComponent. int32 Copied = 0; for (TFieldIterator It(USkyAtmosphereComponent::StaticClass(), EFieldIteratorFlags::ExcludeSuper); It; ++It) { It->CopyCompleteValue_InContainer(NewComp, OldComp); ++Copied; } NewComp->SetRelativeTransform(OldComp->GetRelativeTransform()); NewComp->SetMobility(OldComp->Mobility); // Hors monde enregistre (commandlet), la transformation monde n'est pas recalculee d'elle-meme. NewComp->UpdateComponentToWorld(); OldComp->UpdateComponentToWorld(); Sky->SetActorLabel(Fog->GetActorLabel()); Sky->SetFolderPath(Fog->GetFolderPath()); for (TFieldIterator It(USkyAtmosphereComponent::StaticClass(), EFieldIteratorFlags::ExcludeSuper); It; ++It) { const FString A = ExportProp(*It, OldComp); const FString B = ExportProp(*It, NewComp); if (A != B) { ++Mismatches; UE_LOG(LogLPConvertAtmo, Error, TEXT(" ECART %s : %s / %s"), *It->GetName(), *A, *B); } } if (!NewComp->GetRelativeTransform().Equals(OldComp->GetRelativeTransform()) || !NewComp->GetComponentTransform().Equals(OldComp->GetComponentTransform())) { ++Mismatches; UE_LOG(LogLPConvertAtmo, Error, TEXT(" ECART transformation : %s / %s"), *OldComp->GetComponentTransform().ToString(), *NewComp->GetComponentTransform().ToString()); } UE_LOG(LogLPConvertAtmo, Warning, TEXT(" -> %s : %d propriete(s) copiee(s) et verifiee(s)"), *Sky->GetName(), Copied); World->DestroyActor(Fog); ++Converted; } PRAGMA_ENABLE_DEPRECATION_WARNINGS int32 Result = 0; if (!bDryRun && Converted > 0 && Mismatches == 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(LogLPConvertAtmo, Error, TEXT(" ECHEC de sauvegarde de %s"), *Filename); Result = 1; } else { UE_LOG(LogLPConvertAtmo, Warning, TEXT(" -> %s sauvegardee"), *Filename); } } else if (Mismatches > 0) { UE_LOG(LogLPConvertAtmo, Error, TEXT(" %d ecart(s) : carte NON sauvegardee"), Mismatches); Result = 1; } UE_LOG(LogLPConvertAtmo, Warning, TEXT("=== Termine : %d AtmosphericFog trouve(s), %d converti(s), %d ecart(s) ==="), Fogs.Num(), Converted, Mismatches); World->RemoveFromRoot(); return Result; }