LifePlay-Revival/Source/LifePlayEditorTools/LPSetMaterialUsageCommandlet.cpp
2026-10-22 21:10:39 +02:00

107 lines
3.8 KiB
C++

// 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<FString> Tokens, Switches;
TMap<FString, FString> 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<FString> 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=</lpm_city_<v>/Houses> [-DryRun] [-Report=<f.md>]"));
return Finish(2);
}
Line(FString::Printf(TEXT("# LPSetMaterialUsage %s (%s) : bUsedWithInstancedStaticMeshes"), *Folder, bDryRun ? TEXT("DryRun") : TEXT("ecriture")));
TArray<FString> 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<FAssetRegistryModule>(TEXT("AssetRegistry")).Get();
Registry.ScanPathsSynchronous({ Folder }, /*bForceRescan=*/true);
TArray<FAssetData> 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<UMaterial>(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);
}