#pragma once #include "CoreMinimal.h" #include "MCPHandler.h" #include "MCPAssets.h" #include "MCPUtils.h" #include "Materials/MaterialFunction.h" #include "Materials/MaterialExpression.h" #include "Materials/MaterialExpressionFunctionInput.h" #include "Materials/MaterialExpressionFunctionOutput.h" #include "Materials/MaterialExpressionMaterialFunctionCall.h" #include "Materials/MaterialExpressionScalarParameter.h" #include "Materials/MaterialExpressionVectorParameter.h" #include "Materials/MaterialExpressionTextureSampleParameter2D.h" #include "Materials/MaterialExpressionStaticSwitchParameter.h" #include "Materials/MaterialExpressionConstant.h" #include "Materials/MaterialExpressionConstant3Vector.h" #include "Materials/MaterialExpressionConstant4Vector.h" #include "Materials/MaterialExpressionTextureObjectParameter.h" #include "Materials/MaterialExpressionTextureSample.h" #include "Materials/MaterialExpressionTextureCoordinate.h" #include "Materials/MaterialExpressionComponentMask.h" #include "Materials/MaterialExpressionCustom.h" #include "Engine/Texture.h" #include "UMCPHandler_DumpMaterialFunction.generated.h" // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- UCLASS(meta=(Group="Unclassified")) class UMCPHandler_DumpMaterialFunction : public UObject, public IMCPHandler { GENERATED_BODY() public: UPROPERTY(meta=(Description="MaterialFunction name or package path")) FString MaterialFunction; virtual FString GetDescription() const override { return TEXT("Get detailed info about a material function, including its inputs, outputs, and expressions."); } virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override { MCPAssets Assets; if (!Assets.Exact(MaterialFunction).Errors(Result).ENone().ETwo().Load()) return; UMaterialFunction* MF = Assets.Object(); Result.Appendf(TEXT("MaterialFunction: %s\n"), *MCPUtils::FormatName(MF)); FString Desc = MF->GetDescription(); if (!Desc.IsEmpty()) Result.Appendf(TEXT("Description: %s\n"), *Desc); auto Expressions = MF->GetExpressions(); Result.Appendf(TEXT("Expressions: %d\n"), Expressions.Num()); // Inputs and outputs bool bHasInputs = false; bool bHasOutputs = false; for (UMaterialExpression* Expr : Expressions) { if (!Expr) continue; if (auto* FI = Cast(Expr)) { if (!bHasInputs) { Result.Append(TEXT("\nInputs:\n")); bHasInputs = true; } Result.Appendf(TEXT(" %s\n"), *MCPUtils::FormatName(Expr)); } else if (auto* FO = Cast(Expr)) { if (!bHasOutputs) { Result.Append(TEXT("\nOutputs:\n")); bHasOutputs = true; } Result.Appendf(TEXT(" %s\n"), *MCPUtils::FormatName(Expr)); } } // All expressions Result.Append(TEXT("\nExpression List:\n")); for (UMaterialExpression* Expr : Expressions) { if (!Expr) continue; Result.Appendf(TEXT(" %s"), *MCPUtils::FormatName(Expr)); EmitExpressionDetails(Expr, Result); Result.Append(TEXT("\n")); } } private: void EmitExpressionDetails(UMaterialExpression* Expr, FStringBuilderBase& Result) { if (auto* SP = Cast(Expr)) { Result.Appendf(TEXT(" default=%g"), SP->DefaultValue); if (!SP->Group.IsNone()) Result.Appendf(TEXT(" [%s]"), *SP->Group.ToString()); } else if (auto* VP = Cast(Expr)) { Result.Appendf(TEXT(" default=(%.3f, %.3f, %.3f, %.3f)"), VP->DefaultValue.R, VP->DefaultValue.G, VP->DefaultValue.B, VP->DefaultValue.A); if (!VP->Group.IsNone()) Result.Appendf(TEXT(" [%s]"), *VP->Group.ToString()); } else if (auto* TP = Cast(Expr)) { Result.Appendf(TEXT(" texture=%s"), TP->Texture ? *MCPUtils::FormatName(TP->Texture) : TEXT("None")); if (!TP->Group.IsNone()) Result.Appendf(TEXT(" [%s]"), *TP->Group.ToString()); } else if (auto* SSP = Cast(Expr)) { Result.Appendf(TEXT(" default=%s"), SSP->DefaultValue ? TEXT("true") : TEXT("false")); if (!SSP->Group.IsNone()) Result.Appendf(TEXT(" [%s]"), *SSP->Group.ToString()); } else if (auto* SC = Cast(Expr)) { Result.Appendf(TEXT(" value=%g"), SC->R); } else if (auto* C3 = Cast(Expr)) { Result.Appendf(TEXT(" value=(%.3f, %.3f, %.3f)"), C3->Constant.R, C3->Constant.G, C3->Constant.B); } else if (auto* C4 = Cast(Expr)) { Result.Appendf(TEXT(" value=(%.3f, %.3f, %.3f, %.3f)"), C4->Constant.R, C4->Constant.G, C4->Constant.B, C4->Constant.A); } else if (auto* FC = Cast(Expr)) { if (FC->MaterialFunction) Result.Appendf(TEXT(" calls=%s"), *FC->MaterialFunction->GetPathName()); } else if (auto* TS = Cast(Expr)) { if (TS->Texture) Result.Appendf(TEXT(" texture=%s"), *MCPUtils::FormatName(TS->Texture)); } else if (auto* TC = Cast(Expr)) { Result.Appendf(TEXT(" index=%d tiling=(%.1f, %.1f)"), TC->CoordinateIndex, TC->UTiling, TC->VTiling); } else if (auto* Custom = Cast(Expr)) { Result.Appendf(TEXT(" code_len=%d"), Custom->Code.Len()); } } };