// Lot STM1 (1.2.2). Voir LPSetMaterialUsageCommandlet.h. #include "LPSetMaterialUsageCommandlet.h" #include "AssetRegistry/AssetRegistryModule.h" #include "HAL/FileManager.h" #include "Materials/Material.h" #include "Misc/FileHelper.h" #include "Misc/PackageName.h" #include "UObject/Package.h" #include "UObject/SavePackage.h" DEFINE_LOG_CATEGORY_STATIC(LogLPSetMaterialUsage, Log, All); ULPSetMaterialUsageCommandlet::ULPSetMaterialUsageCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPSetMaterialUsageCommandlet::Main(const FString& Params) { TArray Tokens, Switches; TMap ParamsMap; ParseCommandLine(*Params, Tokens, Switches, ParamsMap); const FString Folder = ParamsMap.FindRef(TEXT("Folder")); const FString ReportPath = ParamsMap.FindRef(TEXT("Report")); const bool bDryRun = Switches.Contains(TEXT("DryRun")); TArray Report; auto Line = [&Report](const FString& Text) { UE_LOG(LogLPSetMaterialUsage, Display, TEXT("%s"), *Text); Report.Add(Text); }; auto Finish = [&](int32 Code) { Line(FString::Printf(TEXT("CODE %d"), Code)); if (!ReportPath.IsEmpty()) { FFileHelper::SaveStringArrayToFile(Report, *ReportPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); } return Code; }; if (Folder.IsEmpty()) { Line(TEXT("usage : -Folder=/Houses> [-DryRun] [-Report=]")); return Finish(2); } Line(FString::Printf(TEXT("# LPSetMaterialUsage %s (%s) : bUsedWithInstancedStaticMeshes"), *Folder, bDryRun ? TEXT("DryRun") : TEXT("ecriture"))); TArray Parts; Folder.ParseIntoArray(Parts, TEXT("/")); if (!(Folder.StartsWith(TEXT("/Game/Heavy/StreetMap/")) || (Parts.Num() >= 1 && Parts[0].StartsWith(TEXT("lpm_city_"))))) { Line(TEXT("ECHEC : dossier hors de /lpm_city_*/ et de /Game/Heavy/StreetMap/ ; rien modifie")); return Finish(1); } IAssetRegistry& Registry = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")).Get(); Registry.ScanPathsSynchronous({ Folder }, /*bForceRescan=*/true); TArray Assets; Registry.GetAssetsByPath(FName(*Folder), Assets, /*bRecursive=*/true); Assets.RemoveAll([](const FAssetData& A) { return A.AssetClassPath != UMaterial::StaticClass()->GetClassPathName(); }); Assets.Sort([](const FAssetData& A, const FAssetData& B) { return A.PackageName.LexicalLess(B.PackageName); }); int32 Already = 0, Set = 0, Saved = 0; for (const FAssetData& Data : Assets) { UMaterial* Material = Cast(Data.GetAsset()); if (!Material) { Line(FString::Printf(TEXT("ECHEC : %s illisible ; arret"), *Data.GetObjectPathString())); return Finish(1); } if (Material->GetUsageByFlag(MATUSAGE_InstancedStaticMeshes)) { ++Already; Line(FString::Printf(TEXT("%s : deja coche"), *Data.GetObjectPathString())); continue; } ++Set; if (bDryRun) { Line(FString::Printf(TEXT("%s : a cocher (DryRun)"), *Data.GetObjectPathString())); continue; } Material->Modify(); Material->SetUsageByFlag(MATUSAGE_InstancedStaticMeshes, true); Material->PostEditChange(); UPackage* Package = Material->GetPackage(); FSavePackageArgs SaveArgs; SaveArgs.TopLevelFlags = RF_Public | RF_Standalone; const FString File = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension()); if (!UPackage::SavePackage(Package, Material, *File, SaveArgs)) { Line(FString::Printf(TEXT("ECHEC : sauvegarde de %s"), *Package->GetName())); return Finish(1); } ++Saved; Line(FString::Printf(TEXT("%s : coche, ecrit (%lld octets)"), *Data.GetObjectPathString(), IFileManager::Get().FileSize(*File))); } Line(FString::Printf(TEXT("materiaux %d ; deja coches %d ; coches %d ; paquets ecrits %d"), Assets.Num(), Already, Set, Saved)); return Finish(0); }