work on material parameters
This commit is contained in:
Binary file not shown.
@@ -24,56 +24,27 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, meta=(Description="Target material instance"))
|
UPROPERTY(EditAnywhere, meta=(Description="Target material instance"))
|
||||||
FString MaterialInstance;
|
FString MaterialInstance;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Parameter name to clear"))
|
UPROPERTY(EditAnywhere, meta=(Description="Parameter ID: 'Name', 'Layer:N:Name', or 'Blend:N:Name'"))
|
||||||
FString Parameter;
|
FString Parameter;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Parameter association: 'Global', 'Layer', or 'Blend'. Default: 'Global'", Optional))
|
|
||||||
FString ParameterAssociation = TEXT("Global");
|
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Layer/blend index (0-based). Only used when ParameterAssociation is 'Layer' or 'Blend'", Optional))
|
|
||||||
int32 ParameterLayer = INDEX_NONE;
|
|
||||||
|
|
||||||
virtual void Register() override
|
virtual void Register() override
|
||||||
{
|
{
|
||||||
UWingServer::AddHandler(this,
|
UWingServer::AddHandler(this,
|
||||||
TEXT("Remove a parameter override from a Material Instance, reverting it to the parent material's value."));
|
TEXT("Remove a parameter override from a Material Instance, reverting it to the parent material's value."));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Handle() override
|
virtual void Handle() override
|
||||||
{
|
{
|
||||||
WingFetcher F(WingOut::Stdout);
|
WingFetcher F(WingOut::Stdout);
|
||||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||||
if (!MI) return;
|
if (!MI) return;
|
||||||
|
|
||||||
// Parse the association string.
|
// Parse the parameter ID.
|
||||||
EMaterialParameterAssociation Association;
|
FMaterialParameterInfo ID;
|
||||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
if (!WingMaterialParameter::ParseID(Parameter, ID, WingOut::Stdout))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FMaterialParameterInfo ParamID(*Parameter, Association, ParameterLayer);
|
if (!WingMaterialParameter::RemoveOverride(ID, MI, WingOut::Stdout)) return
|
||||||
|
WingOut::Stdout.Printf(TEXT("Removed override\n"));
|
||||||
// Remove the override from all parameter arrays.
|
|
||||||
auto RemoveFrom = [&](auto& Arr) {
|
|
||||||
return Arr.RemoveAll([&](auto& Entry) { return Entry.ParameterInfo == ParamID; });
|
|
||||||
};
|
|
||||||
|
|
||||||
int32 Removed = 0;
|
|
||||||
Removed += RemoveFrom(MI->ScalarParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->VectorParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->DoubleVectorParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->TextureParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->TextureCollectionParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->RuntimeVirtualTextureParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->SparseVolumeTextureParameterValues);
|
|
||||||
Removed += RemoveFrom(MI->FontParameterValues);
|
|
||||||
|
|
||||||
if (Removed == 0)
|
|
||||||
{
|
|
||||||
WingOut::Stdout.Printf(TEXT("No override found for parameter '%s' (association=%s layer=%d) on %s"),
|
|
||||||
*Parameter, *ParameterAssociation, ParameterLayer, *WingUtils::FormatName(MI));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WingOut::Stdout.Printf(TEXT("Cleared override for '%s' on %s\n"),
|
|
||||||
*Parameter, *WingUtils::FormatName(MI));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,23 +36,7 @@ public:
|
|||||||
if (!MI) return;
|
if (!MI) return;
|
||||||
|
|
||||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
||||||
|
WingMaterialParameter::PrintAll(AllParams, true);
|
||||||
// Overridden parameters first.
|
if (AllParams.IsEmpty()) WingOut::Stdout.Printf(TEXT("No material parameters.\n"));
|
||||||
bool bHasOverrides = false;
|
|
||||||
for (auto& [Info, Meta] : AllParams)
|
|
||||||
{
|
|
||||||
if (!Meta.bOverride) continue;
|
|
||||||
if (!bHasOverrides) { WingOut::Stdout.Print(TEXT("\nOverridden Parameters:\n")); bHasOverrides = true; }
|
|
||||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inherited (non-overridden) parameters.
|
|
||||||
bool bHasInherited = false;
|
|
||||||
for (auto& [Info, Meta] : AllParams)
|
|
||||||
{
|
|
||||||
if (Meta.bOverride) continue;
|
|
||||||
if (!bHasInherited) { WingOut::Stdout.Print(TEXT("\nInherited Parameters (not overridden):\n")); bHasInherited = true; }
|
|
||||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,15 +25,9 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, meta=(Description="Target material instance"))
|
UPROPERTY(EditAnywhere, meta=(Description="Target material instance"))
|
||||||
FString MaterialInstance;
|
FString MaterialInstance;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Parameter name to set"))
|
UPROPERTY(EditAnywhere, meta=(Description="Parameter ID: 'Name', 'Layer:N:Name', or 'Blend:N:Name'"))
|
||||||
FString Parameter;
|
FString Parameter;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Parameter association: 'Global', 'Layer', or 'Blend'. Default: 'Global'", Optional))
|
|
||||||
FString ParameterAssociation = TEXT("Global");
|
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Layer/blend index (0-based). Only used when ParameterAssociation is 'Layer' or 'Blend'", Optional))
|
|
||||||
int32 ParameterLayer = INDEX_NONE;
|
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="Value to set (uses Unreal text format, e.g. '0.5' for scalar, '(R=1,G=0,B=0,A=1)' for vector)"))
|
UPROPERTY(EditAnywhere, meta=(Description="Value to set (uses Unreal text format, e.g. '0.5' for scalar, '(R=1,G=0,B=0,A=1)' for vector)"))
|
||||||
FString Value;
|
FString Value;
|
||||||
|
|
||||||
@@ -48,30 +42,19 @@ public:
|
|||||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||||
if (!MI) return;
|
if (!MI) return;
|
||||||
|
|
||||||
// Parse the association string.
|
// Parse the parameter ID.
|
||||||
EMaterialParameterAssociation Association;
|
FMaterialParameterInfo ID;
|
||||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
if (!WingMaterialParameter::ParseID(Parameter, ID, WingOut::Stdout))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Build the parameter ID to look up.
|
|
||||||
FMaterialParameterInfo ParamID(*Parameter, Association, ParameterLayer);
|
|
||||||
|
|
||||||
// Find it in the material's parameter map.
|
// Find it in the material's parameter map.
|
||||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
||||||
FMaterialParameterMetadata* Found = AllParams.Find(ParamID);
|
FMaterialParameterMetadata* Meta =
|
||||||
if (!Found)
|
WingMaterialParameter::FindParameter(AllParams, ID, WingOut::Stdout);
|
||||||
{
|
if (!Meta) return;
|
||||||
WingOut::Stdout.Printf(TEXT("No parameter named '%s' with association=%s layer=%d"),
|
if (!WingMaterialParameter::CheckNoCustomPrimitiveData(ID, *Meta, WingOut::Stdout)) return;
|
||||||
*Parameter, *ParameterAssociation, ParameterLayer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Found->PrimitiveDataIndex != INDEX_NONE)
|
|
||||||
{
|
|
||||||
WingOut::Stdout.Printf(TEXT("Parameter '%s' uses custom primitive data and cannot be set on a material instance"), *Parameter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EMaterialParameterType Type = Found->Value.Type;
|
EMaterialParameterType Type = Meta->Value.Type;
|
||||||
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
@@ -83,7 +66,7 @@ public:
|
|||||||
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a float"), *Value);
|
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a float"), *Value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MI->SetScalarParameterValueEditorOnly(ParamID, ScalarValue);
|
MI->SetScalarParameterValueEditorOnly(ID, ScalarValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EMaterialParameterType::Vector:
|
case EMaterialParameterType::Vector:
|
||||||
@@ -94,14 +77,13 @@ public:
|
|||||||
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a color/vector (expected format: '(R=1,G=0,B=0,A=1)')"), *Value);
|
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a color/vector (expected format: '(R=1,G=0,B=0,A=1)')"), *Value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MI->SetVectorParameterValueEditorOnly(ParamID, Color);
|
MI->SetVectorParameterValueEditorOnly(ID, Color);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
WingOut::Stdout.Printf(TEXT("Parameters of type %d (see EMaterialParameterType) are not implemented"), (int)Type);
|
WingOut::Stdout.Printf(TEXT("Parameters of type %d (see EMaterialParameterType) are not implemented"), (int)Type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WingOut::Stdout.Printf(TEXT("Set '%s' = %s on %s\n"),
|
WingOut::Stdout.Printf(TEXT("Assigned.\n"));
|
||||||
*Parameter, *Value, *WingUtils::FormatName(MI));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,11 +35,7 @@ public:
|
|||||||
if (!Mat) return;
|
if (!Mat) return;
|
||||||
|
|
||||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(Mat);
|
auto AllParams = WingMaterialParameter::GetMaterialParameters(Mat);
|
||||||
|
WingMaterialParameter::PrintAll(AllParams, false);
|
||||||
for (auto& [Info, Meta] : AllParams)
|
|
||||||
{
|
|
||||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
|
||||||
}
|
|
||||||
if (AllParams.IsEmpty()) WingOut::Stdout.Printf(TEXT("No material parameters.\n"));
|
if (AllParams.IsEmpty()) WingOut::Stdout.Printf(TEXT("No material parameters.\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingTokenizer.h"
|
|
||||||
#include "Test_Sanitizer.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Test_Sanitizer : public UWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="The string to sanitize"))
|
|
||||||
FString Input;
|
|
||||||
|
|
||||||
virtual void Register() override
|
|
||||||
{
|
|
||||||
UWingServer::AddHandler(this,
|
|
||||||
TEXT("Test the sanitizer by sanitizing a string and printing the result."));
|
|
||||||
}
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingOut::Stdout.Printf(TEXT("%s\n"), *WingTokenizer::ExternalizeID(FName(Input)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingTokenizer.h"
|
|
||||||
#include "Test_Tokenizer.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Test_Tokenizer : public UWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="The string to tokenize"))
|
|
||||||
FString Input;
|
|
||||||
|
|
||||||
virtual void Register() override
|
|
||||||
{
|
|
||||||
UWingServer::AddHandler(this,
|
|
||||||
TEXT("Test the tokenizer by tokenizing a string and printing the result."));
|
|
||||||
}
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingTokenizer T(Input);
|
|
||||||
T.PrintEverything(WingOut::StdoutBuffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingTypes.h"
|
|
||||||
#include "Test_TypeToText.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Test_TypeToText : public UWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="The type name to parse, e.g. 'Array<Vector>'"))
|
|
||||||
FString Input;
|
|
||||||
|
|
||||||
virtual void Register() override
|
|
||||||
{
|
|
||||||
UWingServer::AddHandler(this,
|
|
||||||
TEXT("Test the type parser by parsing a type name and dumping the resulting FEdGraphPinType."));
|
|
||||||
}
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
FEdGraphPinType PinType;
|
|
||||||
UWingTypes::Requirements Require;
|
|
||||||
Require.BlueprintType = false;
|
|
||||||
Require.Blueprintable = false;
|
|
||||||
Require.AllowContainer = true;
|
|
||||||
|
|
||||||
bool OK = UWingTypes::TextToType(Input, PinType, Require, WingOut::Stdout);
|
|
||||||
|
|
||||||
auto& Out = WingOut::Stdout;
|
|
||||||
Out.Printf(TEXT("ParseResult: %s\n"), OK ? TEXT("OK") : TEXT("FAILED"));
|
|
||||||
Out.Printf(TEXT("PinCategory: %s\n"), *PinType.PinCategory.ToString());
|
|
||||||
Out.Printf(TEXT("PinSubCategory: %s\n"), *PinType.PinSubCategory.ToString());
|
|
||||||
Out.Printf(TEXT("PinSubCategoryObject: %s\n"),
|
|
||||||
PinType.PinSubCategoryObject.IsValid()
|
|
||||||
? *PinType.PinSubCategoryObject->GetPathName()
|
|
||||||
: TEXT("(none)"));
|
|
||||||
Out.Printf(TEXT("ContainerType: %d\n"), (int32)PinType.ContainerType);
|
|
||||||
if (PinType.IsMap())
|
|
||||||
{
|
|
||||||
Out.Printf(TEXT("ValueTerminalCategory: %s\n"), *PinType.PinValueType.TerminalCategory.ToString());
|
|
||||||
Out.Printf(TEXT("ValueTerminalSubCategory: %s\n"), *PinType.PinValueType.TerminalSubCategory.ToString());
|
|
||||||
Out.Printf(TEXT("ValueTerminalSubCategoryObject: %s\n"),
|
|
||||||
PinType.PinValueType.TerminalSubCategoryObject.IsValid()
|
|
||||||
? *PinType.PinValueType.TerminalSubCategoryObject->GetPathName()
|
|
||||||
: TEXT("(none)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OK)
|
|
||||||
{
|
|
||||||
FString RoundTrip = UWingTypes::TypeToText(PinType);
|
|
||||||
Out.Printf(TEXT("TypeToText: %s\n"), RoundTrip.IsEmpty() ? TEXT("(empty)") : *RoundTrip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingTokenizer.h"
|
|
||||||
#include "Test_Unsanitize.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Test_Unsanitize : public UWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(EditAnywhere, meta=(Description="The sanitized identifier to unsanitize"))
|
|
||||||
FString Input;
|
|
||||||
|
|
||||||
virtual void Register() override
|
|
||||||
{
|
|
||||||
UWingServer::AddHandler(this,
|
|
||||||
TEXT("Test the unsanitizer by unsanitizing a string and printing the result."));
|
|
||||||
}
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
FString Error;
|
|
||||||
FName Result = WingTokenizer::TryInternalizeID(Input, Error);
|
|
||||||
if (!Error.IsEmpty())
|
|
||||||
{
|
|
||||||
WingOut::Stdout.Printf(TEXT("Error: %s\n"), *Error);
|
|
||||||
}
|
|
||||||
if (!Result.IsNone())
|
|
||||||
{
|
|
||||||
WingOut::Stdout.Printf(TEXT("Result: %s\n"), *Result.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
#include "WingMaterialParameter.h"
|
#include "WingMaterialParameter.h"
|
||||||
#include "WingUtils.h"
|
#include "WingUtils.h"
|
||||||
|
#include "WingTokenizer.h"
|
||||||
#include "WingServer.h"
|
#include "WingServer.h"
|
||||||
|
|
||||||
TMap<FMaterialParameterInfo, FMaterialParameterMetadata> WingMaterialParameter::GetMaterialParameters(UMaterialInterface* Material)
|
WingMaterialParameter::InfoMetaMap WingMaterialParameter::GetMaterialParameters(UMaterialInterface* Material)
|
||||||
{
|
{
|
||||||
TMap<FMaterialParameterInfo, FMaterialParameterMetadata> Result;
|
InfoMetaMap Result;
|
||||||
if (!Material) return Result;
|
if (!Material) return Result;
|
||||||
TMap<FMaterialParameterInfo, FMaterialParameterMetadata> Temp;
|
InfoMetaMap Temp;
|
||||||
for (int32 i = 0; i < (int32)EMaterialParameterType::NumRuntime; i++)
|
for (int32 i = 0; i < (int32)EMaterialParameterType::NumRuntime; i++)
|
||||||
{
|
{
|
||||||
Material->GetAllParametersOfType((EMaterialParameterType)i, Temp);
|
Material->GetAllParametersOfType((EMaterialParameterType)i, Temp);
|
||||||
@@ -31,48 +32,183 @@ bool WingMaterialParameter::ParseMaterialParameterAssociation(const FString& Str
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingMaterialParameter::FormatMaterialParameter(const FMaterialParameterInfo& Info, const FMaterialParameterMetadata& Meta)
|
void WingMaterialParameter::ReportBadToken(WingTokenizer &Tok, const TCHAR *Expected, WingOut Errors)
|
||||||
{
|
{
|
||||||
// Association prefix for layer/blend parameters.
|
FString Whole = Tok.GetRange(FName(), 1000);
|
||||||
FString Prefix;
|
Tok.SaveCursor(FName());
|
||||||
if (Info.Association == LayerParameter)
|
FString Next = Tok.GetRange(FName(), 1);
|
||||||
Prefix = FString::Printf(TEXT("[Layer %d] "), Info.Index);
|
Errors.Printf(TEXT("Parsing %s, near %s: expected %s"), *Whole, *Next, Expected);
|
||||||
else if (Info.Association == BlendParameter)
|
}
|
||||||
Prefix = FString::Printf(TEXT("[Blend %d] "), Info.Index);
|
|
||||||
|
|
||||||
switch (Meta.Value.Type)
|
FString WingMaterialParameter::StringID(const FMaterialParameterInfo &ID)
|
||||||
{
|
{
|
||||||
case EMaterialParameterType::Scalar:
|
FString Ext = WingUtils::ExternalizeID(ID.Name);
|
||||||
WingOut::Stdout.Printf(TEXT(" %sScalar \"%s\" = %g\n"), *Prefix, *Info.Name.ToString(), Meta.Value.AsScalar());
|
if (ID.Association != EMaterialParameterAssociation::GlobalParameter)
|
||||||
break;
|
|
||||||
case EMaterialParameterType::Vector:
|
|
||||||
{
|
{
|
||||||
FLinearColor C = Meta.Value.AsLinearColor();
|
const TCHAR *Prefix = TEXT("Layer");
|
||||||
WingOut::Stdout.Printf(TEXT(" %sVector \"%s\" = (R=%.3f, G=%.3f, B=%.3f, A=%.3f)\n"),
|
if (ID.Association == EMaterialParameterAssociation::BlendParameter)
|
||||||
*Prefix, *Info.Name.ToString(), C.R, C.G, C.B, C.A);
|
Prefix = TEXT("Blend");
|
||||||
break;
|
return FString::Printf(TEXT("%s:%d:%s"), Prefix, ID.Index, *Ext);
|
||||||
}
|
}
|
||||||
case EMaterialParameterType::DoubleVector:
|
else
|
||||||
{
|
{
|
||||||
FVector4d V = Meta.Value.AsVector4d();
|
return Ext;
|
||||||
WingOut::Stdout.Printf(TEXT(" %sDoubleVector \"%s\" = (%.3f, %.3f, %.3f, %.3f)\n"),
|
|
||||||
*Prefix, *Info.Name.ToString(), V.X, V.Y, V.Z, V.W);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EMaterialParameterType::Texture:
|
|
||||||
{
|
|
||||||
UTexture* Tex = Cast<UTexture>(Meta.Value.AsTextureObject());
|
|
||||||
WingOut::Stdout.Printf(TEXT(" %sTexture \"%s\" = %s\n"),
|
|
||||||
*Prefix, *Info.Name.ToString(), Tex ? *WingUtils::FormatName(Tex) : TEXT("None"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EMaterialParameterType::StaticSwitch:
|
|
||||||
WingOut::Stdout.Printf(TEXT(" %sStaticSwitch \"%s\" = %s\n"),
|
|
||||||
*Prefix, *Info.Name.ToString(), Meta.Value.AsStaticSwitch() ? TEXT("true") : TEXT("false"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
WingOut::Stdout.Printf(TEXT(" %sType%d \"%s\"\n"), *Prefix, (int)Meta.Value.Type, *Info.Name.ToString());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WingMaterialParameter::ParseID(const FString& IDString, FMaterialParameterInfo& ID, WingOut Errors)
|
||||||
|
{
|
||||||
|
WingTokenizer Tok(IDString);
|
||||||
|
|
||||||
|
ID.Association = EMaterialParameterAssociation::GlobalParameter;
|
||||||
|
ID.Index = 0;
|
||||||
|
ID.Name = FName();
|
||||||
|
|
||||||
|
// Parse the Layer or blend prefix.
|
||||||
|
if (Tok.TokenIs(TEXT("Layer")) || Tok.TokenIs(TEXT("Blend")))
|
||||||
|
{
|
||||||
|
if (Tok.NextName() == TEXT("Layer"))
|
||||||
|
ID.Association = EMaterialParameterAssociation::LayerParameter;
|
||||||
|
else
|
||||||
|
ID.Association = EMaterialParameterAssociation::BlendParameter;
|
||||||
|
Tok.Advance();
|
||||||
|
|
||||||
|
if (!Tok.TokenIs(':'))
|
||||||
|
{ ReportBadToken(Tok, TEXT("colon"), Errors); return false; }
|
||||||
|
Tok.Advance();
|
||||||
|
|
||||||
|
if ((!Tok.TokenIs(Tok.Identifier)) ||
|
||||||
|
(!LexTryParseString(ID.Index, *Tok.NextName().ToString())))
|
||||||
|
{ ReportBadToken(Tok, TEXT("integer"), Errors); return false; }
|
||||||
|
Tok.Advance();
|
||||||
|
|
||||||
|
if ((ID.Index < 0)||(ID.Index > 50))
|
||||||
|
{
|
||||||
|
Errors.Printf(TEXT("Layer/Blend index outside of reasonable range\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Tok.TokenIs(':'))
|
||||||
|
{ ReportBadToken(Tok, TEXT("colon"), Errors); return false; }
|
||||||
|
Tok.Advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the parameter name
|
||||||
|
if (!Tok.TokenIs(Tok.Identifier))
|
||||||
|
{ ReportBadToken(Tok, TEXT("parameter name"), Errors); return false; }
|
||||||
|
ID.Name = Tok.NextName();
|
||||||
|
Tok.Advance();
|
||||||
|
|
||||||
|
if (!Tok.TokenIs(0))
|
||||||
|
{ ReportBadToken(Tok, TEXT("end of input"), Errors); return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FMaterialParameterMetadata *WingMaterialParameter::FindParameter(
|
||||||
|
InfoMetaMap &Map, const FMaterialParameterInfo &ID, WingOut Errors)
|
||||||
|
{
|
||||||
|
FMaterialParameterMetadata* Found = Map.Find(ID);
|
||||||
|
if (!Found)
|
||||||
|
{
|
||||||
|
Errors.Printf(TEXT("No parameter named '%s' in this material"), *StringID(ID));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingMaterialParameter::CheckNoCustomPrimitiveData(
|
||||||
|
const FMaterialParameterInfo &ID, const FMaterialParameterMetadata &Data, WingOut Errors)
|
||||||
|
{
|
||||||
|
if (Data.PrimitiveDataIndex != INDEX_NONE)
|
||||||
|
{
|
||||||
|
Errors.Printf(
|
||||||
|
TEXT("Parameter '%s' uses custom primitive data, which cannot be set on a material instance"),
|
||||||
|
*StringID(ID));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FString WingMaterialParameter::FormatValue(const FMaterialParameterValue& Value)
|
||||||
|
{
|
||||||
|
switch (Value.Type)
|
||||||
|
{
|
||||||
|
case EMaterialParameterType::Scalar: {
|
||||||
|
return FString::Printf(TEXT("scalar(%g)"), Value.AsScalar());
|
||||||
|
}
|
||||||
|
case EMaterialParameterType::Vector: {
|
||||||
|
return FString::Printf(TEXT("vector(%s)"), *Value.AsLinearColor().ToString());
|
||||||
|
}
|
||||||
|
case EMaterialParameterType::DoubleVector: {
|
||||||
|
return FString::Printf(TEXT("doublevector(%s)"), *Value.AsLinearColor().ToString());
|
||||||
|
}
|
||||||
|
case EMaterialParameterType::Texture: {
|
||||||
|
UTexture* Tex = Cast<UTexture>(Value.AsTextureObject());
|
||||||
|
return FString::Printf(TEXT("texture(%s)"), *Tex->GetPathName());
|
||||||
|
}
|
||||||
|
case EMaterialParameterType::StaticSwitch: {
|
||||||
|
const TCHAR *Str = Value.AsStaticSwitch() ? TEXT("true") : TEXT("false");
|
||||||
|
return FString::Printf(TEXT("staticswitch(%s)"), Str);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return FString::Printf(TEXT("unknown(%d)"), (int)Value.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingMaterialParameter::RemoveOverride(
|
||||||
|
const FMaterialParameterInfo &ID, UMaterialInstanceConstant *MI, WingOut Errors)
|
||||||
|
{
|
||||||
|
// Remove the override from all parameter arrays.
|
||||||
|
auto RemoveFrom = [&](auto& Arr) {
|
||||||
|
return Arr.RemoveAll([&](auto& Entry) { return Entry.ParameterInfo == ID; });
|
||||||
|
};
|
||||||
|
|
||||||
|
int32 Removed = 0;
|
||||||
|
Removed += RemoveFrom(MI->ScalarParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->VectorParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->DoubleVectorParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->TextureParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->TextureCollectionParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->RuntimeVirtualTextureParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->SparseVolumeTextureParameterValues);
|
||||||
|
Removed += RemoveFrom(MI->FontParameterValues);
|
||||||
|
|
||||||
|
if (Removed == 0)
|
||||||
|
{
|
||||||
|
Errors.Printf(TEXT("No override found for parameter '%s'"), *StringID(ID));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WingMaterialParameter::Print(
|
||||||
|
const FMaterialParameterInfo &Info, const FMaterialParameterMetadata &Meta)
|
||||||
|
{
|
||||||
|
WingOut::Stdout.Printf(TEXT(" %s %s\n"),
|
||||||
|
*WingMaterialParameter::StringID(Info), *WingMaterialParameter::FormatValue(Meta.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingMaterialParameter::PrintAll(const InfoMetaMap &Params, bool Headings)
|
||||||
|
{
|
||||||
|
// Overridden parameters first.
|
||||||
|
bool bHasOverrides = false;
|
||||||
|
for (auto& [Info, Meta] : Params)
|
||||||
|
{
|
||||||
|
if (!Meta.bOverride) continue;
|
||||||
|
if (Headings && !bHasOverrides)
|
||||||
|
{ WingOut::Stdout.Print(TEXT("\nOverridden Parameters:\n")); bHasOverrides = true; }
|
||||||
|
WingMaterialParameter::Print(Info, Meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inherited (non-overridden) parameters.
|
||||||
|
bool bHasInherited = false;
|
||||||
|
for (auto& [Info, Meta] : Params)
|
||||||
|
{
|
||||||
|
if (Meta.bOverride) continue;
|
||||||
|
if (Headings && !bHasInherited)
|
||||||
|
{ WingOut::Stdout.Print(TEXT("\nInherited Parameters (not overridden):\n")); bHasInherited = true; }
|
||||||
|
WingMaterialParameter::Print(Info, Meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -249,16 +249,16 @@ void WingTokenizer::SaveCursor(FName Name)
|
|||||||
SavedCursor.Emplace(Name, Cursor);
|
SavedCursor.Emplace(Name, Cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FStringView WingTokenizer::GetRange(FName SavePos, int Extra) const
|
FString WingTokenizer::GetRange(FName SavePos, int Extra) const
|
||||||
{
|
{
|
||||||
int Lo = 0;
|
int Lo = 0;
|
||||||
for (auto &Pair : SavedCursor) if (Pair.Key == SavePos) Lo = Pair.Value;
|
for (auto &Pair : SavedCursor) if (Pair.Key == SavePos) Lo = Pair.Value;
|
||||||
int Hi = (Next - Tokens.GetData()) + Extra;
|
int Hi = (Next - Tokens.GetData()) + Extra;
|
||||||
Hi = FMath::Clamp(Hi, Lo, Tokens.Num());
|
Hi = FMath::Clamp(Hi, Lo, Tokens.Num());
|
||||||
if (Lo >= Hi) return FStringView();
|
if (Lo >= Hi) return FString();
|
||||||
const TCHAR* Start = Tokens[Lo].Source.GetData();
|
const TCHAR* Start = Tokens[Lo].Source.GetData();
|
||||||
const TCHAR* End = Tokens[Hi - 1].Source.GetData() + Tokens[Hi - 1].Source.Len();
|
const TCHAR* End = Tokens[Hi - 1].Source.GetData() + Tokens[Hi - 1].Source.Len();
|
||||||
return FStringView(Start, End - Start);
|
return FString(End - Start, Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingTokenizer::PrintEverything(FStringBuilderBase &Out) const
|
void WingTokenizer::PrintEverything(FStringBuilderBase &Out) const
|
||||||
|
|||||||
@@ -2,13 +2,63 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "Materials/Material.h"
|
#include "Materials/Material.h"
|
||||||
|
#include "WingTokenizer.h"
|
||||||
|
#include "Materials/MaterialInstanceConstant.h"
|
||||||
#include "WingHandler.h"
|
#include "WingHandler.h"
|
||||||
|
|
||||||
class WingMaterialParameter
|
class WingMaterialParameter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static TMap<FMaterialParameterInfo, FMaterialParameterMetadata> GetMaterialParameters(UMaterialInterface* Material);
|
using InfoMetaMap = TMap<FMaterialParameterInfo, FMaterialParameterMetadata>;
|
||||||
|
|
||||||
|
// Get all the material parameters of the specified material including
|
||||||
|
// both parameters that have been overridden and those that haven't.
|
||||||
|
//
|
||||||
|
static InfoMetaMap GetMaterialParameters(UMaterialInterface* Material);
|
||||||
|
|
||||||
|
// Find a material parameter in the InfoMap.
|
||||||
|
// If it doesn't exist, or report an error and return nullptr.
|
||||||
|
//
|
||||||
|
static FMaterialParameterMetadata *FindParameter(
|
||||||
|
InfoMetaMap &Map, const FMaterialParameterInfo &ID, WingOut Errors);
|
||||||
|
|
||||||
|
// If the material uses custom primitive data, print an error
|
||||||
|
// and return false.
|
||||||
|
//
|
||||||
|
static bool CheckNoCustomPrimitiveData(
|
||||||
|
const FMaterialParameterInfo &ID, const FMaterialParameterMetadata &Data, WingOut Errors);
|
||||||
|
|
||||||
|
// Convert a parameter ID into an ID string.
|
||||||
|
//
|
||||||
|
static bool ParseID(const FString& Str, FMaterialParameterInfo& ID, WingOut Errors);
|
||||||
|
|
||||||
|
// Parse a parameter ID String into a parameter ID.
|
||||||
|
//
|
||||||
|
static FString StringID(const FMaterialParameterInfo& ID);
|
||||||
|
|
||||||
|
// Remove a material parameter override from a material instance.
|
||||||
|
// If there is no override, print an error and return false.
|
||||||
|
//
|
||||||
|
static bool RemoveOverride(
|
||||||
|
const FMaterialParameterInfo &ID, UMaterialInstanceConstant *MI, WingOut Errors);
|
||||||
|
|
||||||
|
// Format a material parameter value.
|
||||||
|
//
|
||||||
|
static FString FormatValue(const FMaterialParameterValue& Value);
|
||||||
|
|
||||||
|
// Print out a material parameter with ID.
|
||||||
|
//
|
||||||
|
static void Print(const FMaterialParameterInfo &Info, const FMaterialParameterMetadata &Meta);
|
||||||
|
|
||||||
|
// Print out a map full of material parameters. If Headings is
|
||||||
|
// true, the parameters are grouped by inherited/overridden.
|
||||||
|
//
|
||||||
|
static void PrintAll(const InfoMetaMap &Params, bool Headings);
|
||||||
|
|
||||||
static bool ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation, WingOut Errors);
|
static bool ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation, WingOut Errors);
|
||||||
static void FormatMaterialParameter(const FMaterialParameterInfo& Info, const FMaterialParameterMetadata& Meta);
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void ReportBadToken(WingTokenizer &Tok, const TCHAR *Expected, WingOut Errors);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingHandler.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -130,7 +130,7 @@ struct WingTokenizer
|
|||||||
|
|
||||||
// Get the input text from a saved cursor position to the current
|
// Get the input text from a saved cursor position to the current
|
||||||
// cursor, optionally including additional tokens.
|
// cursor, optionally including additional tokens.
|
||||||
FStringView GetRange(FName SavePos, int32 Extra = 0) const;
|
FString GetRange(FName SavePos, int32 Extra = 0) const;
|
||||||
|
|
||||||
// Tokenize a line of input. The tokens are stored in
|
// Tokenize a line of input. The tokens are stored in
|
||||||
// the token array, and the cursor is positioned on the first
|
// the token array, and the cursor is positioned on the first
|
||||||
|
|||||||
Reference in New Issue
Block a user