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"))
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
UWingServer::AddHandler(this,
|
||||
TEXT("Remove a parameter override from a Material Instance, reverting it to the parent material's value."));
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||
if (!MI) return;
|
||||
|
||||
// Parse the association string.
|
||||
EMaterialParameterAssociation Association;
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
||||
// Parse the parameter ID.
|
||||
FMaterialParameterInfo ID;
|
||||
if (!WingMaterialParameter::ParseID(Parameter, ID, WingOut::Stdout))
|
||||
return;
|
||||
|
||||
FMaterialParameterInfo ParamID(*Parameter, Association, ParameterLayer);
|
||||
|
||||
// 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));
|
||||
if (!WingMaterialParameter::RemoveOverride(ID, MI, WingOut::Stdout)) return
|
||||
WingOut::Stdout.Printf(TEXT("Removed override\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,23 +36,7 @@ public:
|
||||
if (!MI) return;
|
||||
|
||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
||||
|
||||
// Overridden parameters first.
|
||||
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);
|
||||
}
|
||||
WingMaterialParameter::PrintAll(AllParams, true);
|
||||
if (AllParams.IsEmpty()) WingOut::Stdout.Printf(TEXT("No material parameters.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,15 +25,9 @@ public:
|
||||
UPROPERTY(EditAnywhere, meta=(Description="Target material instance"))
|
||||
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;
|
||||
|
||||
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)"))
|
||||
FString Value;
|
||||
|
||||
@@ -48,30 +42,19 @@ public:
|
||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||
if (!MI) return;
|
||||
|
||||
// Parse the association string.
|
||||
EMaterialParameterAssociation Association;
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
||||
// Parse the parameter ID.
|
||||
FMaterialParameterInfo ID;
|
||||
if (!WingMaterialParameter::ParseID(Parameter, ID, WingOut::Stdout))
|
||||
return;
|
||||
|
||||
// Build the parameter ID to look up.
|
||||
FMaterialParameterInfo ParamID(*Parameter, Association, ParameterLayer);
|
||||
|
||||
// Find it in the material's parameter map.
|
||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(MI);
|
||||
FMaterialParameterMetadata* Found = AllParams.Find(ParamID);
|
||||
if (!Found)
|
||||
{
|
||||
WingOut::Stdout.Printf(TEXT("No parameter named '%s' with association=%s layer=%d"),
|
||||
*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;
|
||||
}
|
||||
FMaterialParameterMetadata* Meta =
|
||||
WingMaterialParameter::FindParameter(AllParams, ID, WingOut::Stdout);
|
||||
if (!Meta) return;
|
||||
if (!WingMaterialParameter::CheckNoCustomPrimitiveData(ID, *Meta, WingOut::Stdout)) return;
|
||||
|
||||
EMaterialParameterType Type = Found->Value.Type;
|
||||
EMaterialParameterType Type = Meta->Value.Type;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
@@ -83,7 +66,7 @@ public:
|
||||
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a float"), *Value);
|
||||
return;
|
||||
}
|
||||
MI->SetScalarParameterValueEditorOnly(ParamID, ScalarValue);
|
||||
MI->SetScalarParameterValueEditorOnly(ID, ScalarValue);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
MI->SetVectorParameterValueEditorOnly(ParamID, Color);
|
||||
MI->SetVectorParameterValueEditorOnly(ID, Color);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WingOut::Stdout.Printf(TEXT("Parameters of type %d (see EMaterialParameterType) are not implemented"), (int)Type);
|
||||
return;
|
||||
}
|
||||
WingOut::Stdout.Printf(TEXT("Set '%s' = %s on %s\n"),
|
||||
*Parameter, *Value, *WingUtils::FormatName(MI));
|
||||
WingOut::Stdout.Printf(TEXT("Assigned.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,11 +35,7 @@ public:
|
||||
if (!Mat) return;
|
||||
|
||||
auto AllParams = WingMaterialParameter::GetMaterialParameters(Mat);
|
||||
|
||||
for (auto& [Info, Meta] : AllParams)
|
||||
{
|
||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
||||
}
|
||||
WingMaterialParameter::PrintAll(AllParams, false);
|
||||
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 "WingUtils.h"
|
||||
#include "WingTokenizer.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;
|
||||
TMap<FMaterialParameterInfo, FMaterialParameterMetadata> Temp;
|
||||
InfoMetaMap Temp;
|
||||
for (int32 i = 0; i < (int32)EMaterialParameterType::NumRuntime; i++)
|
||||
{
|
||||
Material->GetAllParametersOfType((EMaterialParameterType)i, Temp);
|
||||
@@ -31,48 +32,183 @@ bool WingMaterialParameter::ParseMaterialParameterAssociation(const FString& Str
|
||||
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 Prefix;
|
||||
if (Info.Association == LayerParameter)
|
||||
Prefix = FString::Printf(TEXT("[Layer %d] "), Info.Index);
|
||||
else if (Info.Association == BlendParameter)
|
||||
Prefix = FString::Printf(TEXT("[Blend %d] "), Info.Index);
|
||||
FString Whole = Tok.GetRange(FName(), 1000);
|
||||
Tok.SaveCursor(FName());
|
||||
FString Next = Tok.GetRange(FName(), 1);
|
||||
Errors.Printf(TEXT("Parsing %s, near %s: expected %s"), *Whole, *Next, Expected);
|
||||
}
|
||||
|
||||
switch (Meta.Value.Type)
|
||||
FString WingMaterialParameter::StringID(const FMaterialParameterInfo &ID)
|
||||
{
|
||||
case EMaterialParameterType::Scalar:
|
||||
WingOut::Stdout.Printf(TEXT(" %sScalar \"%s\" = %g\n"), *Prefix, *Info.Name.ToString(), Meta.Value.AsScalar());
|
||||
break;
|
||||
case EMaterialParameterType::Vector:
|
||||
FString Ext = WingUtils::ExternalizeID(ID.Name);
|
||||
if (ID.Association != EMaterialParameterAssociation::GlobalParameter)
|
||||
{
|
||||
FLinearColor C = Meta.Value.AsLinearColor();
|
||||
WingOut::Stdout.Printf(TEXT(" %sVector \"%s\" = (R=%.3f, G=%.3f, B=%.3f, A=%.3f)\n"),
|
||||
*Prefix, *Info.Name.ToString(), C.R, C.G, C.B, C.A);
|
||||
break;
|
||||
const TCHAR *Prefix = TEXT("Layer");
|
||||
if (ID.Association == EMaterialParameterAssociation::BlendParameter)
|
||||
Prefix = TEXT("Blend");
|
||||
return FString::Printf(TEXT("%s:%d:%s"), Prefix, ID.Index, *Ext);
|
||||
}
|
||||
case EMaterialParameterType::DoubleVector:
|
||||
else
|
||||
{
|
||||
FVector4d V = Meta.Value.AsVector4d();
|
||||
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;
|
||||
return Ext;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
FStringView WingTokenizer::GetRange(FName SavePos, int Extra) const
|
||||
FString WingTokenizer::GetRange(FName SavePos, int Extra) const
|
||||
{
|
||||
int Lo = 0;
|
||||
for (auto &Pair : SavedCursor) if (Pair.Key == SavePos) Lo = Pair.Value;
|
||||
int Hi = (Next - Tokens.GetData()) + Extra;
|
||||
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* 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
|
||||
|
||||
@@ -2,13 +2,63 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Materials/Material.h"
|
||||
#include "WingTokenizer.h"
|
||||
#include "Materials/MaterialInstanceConstant.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
class WingMaterialParameter
|
||||
{
|
||||
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 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
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
//
|
||||
@@ -130,7 +130,7 @@ struct WingTokenizer
|
||||
|
||||
// Get the input text from a saved cursor position to the current
|
||||
// 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
|
||||
// the token array, and the cursor is positioned on the first
|
||||
|
||||
Reference in New Issue
Block a user