112 lines
4.2 KiB
C++
112 lines
4.2 KiB
C++
|
|
// Lot STM1 (COMMUN-28 S6). Voir LPDumpMaterialCommandlet.h.
|
||
|
|
|
||
|
|
#include "LPDumpMaterialCommandlet.h"
|
||
|
|
|
||
|
|
#include "Materials/Material.h"
|
||
|
|
#include "Materials/MaterialExpression.h"
|
||
|
|
#include "Misc/FileHelper.h"
|
||
|
|
#include "UObject/UnrealType.h"
|
||
|
|
|
||
|
|
DEFINE_LOG_CATEGORY_STATIC(LogLPDumpMaterial, Log, All);
|
||
|
|
|
||
|
|
ULPDumpMaterialCommandlet::ULPDumpMaterialCommandlet()
|
||
|
|
{
|
||
|
|
IsClient = false;
|
||
|
|
IsServer = false;
|
||
|
|
IsEditor = true;
|
||
|
|
LogToConsole = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
int32 ULPDumpMaterialCommandlet::Main(const FString& Params)
|
||
|
|
{
|
||
|
|
TArray<FString> Tokens, Switches;
|
||
|
|
TMap<FString, FString> ParamsMap;
|
||
|
|
ParseCommandLine(*Params, Tokens, Switches, ParamsMap);
|
||
|
|
const FString ReportPath = ParamsMap.FindRef(TEXT("Report"));
|
||
|
|
TArray<FString> Paths;
|
||
|
|
ParamsMap.FindRef(TEXT("Material")).ParseIntoArray(Paths, TEXT(";"));
|
||
|
|
|
||
|
|
TArray<FString> Report;
|
||
|
|
auto Line = [&Report](const FString& Text)
|
||
|
|
{
|
||
|
|
UE_LOG(LogLPDumpMaterial, 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 (Paths.IsEmpty())
|
||
|
|
{
|
||
|
|
Line(TEXT("usage : -Material=<objet>[;<objet>...] [-Report=<f.md>]"));
|
||
|
|
return Finish(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const FString& Path : Paths)
|
||
|
|
{
|
||
|
|
UMaterial* Material = LoadObject<UMaterial>(nullptr, *Path);
|
||
|
|
Line(FString::Printf(TEXT("# %s"), *Path));
|
||
|
|
if (!Material)
|
||
|
|
{
|
||
|
|
Line(TEXT("ECHEC : UMaterial introuvable"));
|
||
|
|
return Finish(1);
|
||
|
|
}
|
||
|
|
const TConstArrayView<TObjectPtr<UMaterialExpression>> Expressions = Material->GetExpressions();
|
||
|
|
auto IndexOf = [&Expressions](const UMaterialExpression* E)
|
||
|
|
{
|
||
|
|
for (int32 I = 0; I < Expressions.Num(); ++I) if (Expressions[I] == E) return I;
|
||
|
|
return int32(INDEX_NONE);
|
||
|
|
};
|
||
|
|
Line(FString::Printf(TEXT("domaine %s ; melange %s ; ombrage %s ; deux faces %d ; noeuds %d"),
|
||
|
|
*StaticEnum<EMaterialDomain>()->GetNameStringByValue(int64(Material->MaterialDomain)),
|
||
|
|
*StaticEnum<EBlendMode>()->GetNameStringByValue(int64(Material->BlendMode)),
|
||
|
|
*StaticEnum<EMaterialShadingModel>()->GetNameStringByValue(int64(Material->GetShadingModels().GetFirstShadingModel())),
|
||
|
|
Material->IsTwoSided() ? 1 : 0, Expressions.Num()));
|
||
|
|
if (const UMaterialEditorOnlyData* Data = Material->GetEditorOnlyData())
|
||
|
|
{
|
||
|
|
const TPair<const TCHAR*, const FExpressionInput*> Inputs[] = {
|
||
|
|
{ TEXT("BaseColor"), &Data->BaseColor }, { TEXT("EmissiveColor"), &Data->EmissiveColor }, { TEXT("Normal"), &Data->Normal },
|
||
|
|
{ TEXT("Metallic"), &Data->Metallic }, { TEXT("Roughness"), &Data->Roughness }, { TEXT("Specular"), &Data->Specular },
|
||
|
|
{ TEXT("Opacity"), &Data->Opacity }, { TEXT("OpacityMask"), &Data->OpacityMask }, { TEXT("WorldPositionOffset"), &Data->WorldPositionOffset } };
|
||
|
|
for (const TPair<const TCHAR*, const FExpressionInput*>& Input : Inputs)
|
||
|
|
{
|
||
|
|
if (Input.Value->Expression)
|
||
|
|
{
|
||
|
|
Line(FString::Printf(TEXT("entree %s <- noeud %d (%s), sortie %d"), Input.Key, IndexOf(Input.Value->Expression),
|
||
|
|
*Input.Value->Expression->GetClass()->GetName(), Input.Value->OutputIndex));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (int32 I = 0; I < Expressions.Num(); ++I)
|
||
|
|
{
|
||
|
|
UMaterialExpression* E = Expressions[I];
|
||
|
|
if (!E) continue;
|
||
|
|
TArray<FString> Props;
|
||
|
|
for (TFieldIterator<FProperty> It(E->GetClass(), EFieldIteratorFlags::ExcludeSuper); It; ++It)
|
||
|
|
{
|
||
|
|
if (CastField<FStructProperty>(*It) && CastField<FStructProperty>(*It)->Struct->GetName().Contains(TEXT("ExpressionInput"))) continue;
|
||
|
|
FString Value;
|
||
|
|
It->ExportTextItem_InContainer(Value, E, nullptr, nullptr, PPF_None);
|
||
|
|
if (Value.Len() > 120) Value = Value.Left(120) + TEXT("...");
|
||
|
|
Props.Add(FString::Printf(TEXT("%s=%s"), *It->GetName(), *Value));
|
||
|
|
}
|
||
|
|
TArray<FString> Links;
|
||
|
|
for (FExpressionInputIterator It{ E }; It; ++It)
|
||
|
|
{
|
||
|
|
if (It->Expression)
|
||
|
|
{
|
||
|
|
Links.Add(FString::Printf(TEXT("%s<-%d"), *E->GetInputName(It.Index).ToString(), IndexOf(It->Expression)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Line(FString::Printf(TEXT(" [%d] %s \"%s\" | %s | entrees : %s"), I, *E->GetClass()->GetName(), *E->GetDescription(),
|
||
|
|
*FString::Join(Props, TEXT(" ; ")), Links.IsEmpty() ? TEXT("-") : *FString::Join(Links, TEXT(", "))));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return Finish(0);
|
||
|
|
}
|