More handler wokr
This commit is contained in:
@@ -1,66 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "MCPHandler.h"
|
|
||||||
#include "MCPFetcher.h"
|
|
||||||
#include "MCPUtils.h"
|
|
||||||
#include "EdGraph/EdGraphPin.h"
|
|
||||||
#include "GraphPin_GetDetails.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// HandleGetPinInfo — detailed information about a specific pin
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UMCP_GraphPin_GetDetails : public UObject, public IMCPHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Path to the pin, e.g. /Game/Widgets/WB_Hotkeys,node:MyNode,pin:Result"))
|
|
||||||
FString Pin;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("Get detailed information about a specific pin on a blueprint node, "
|
|
||||||
"including type, connections, and default values.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
|
||||||
{
|
|
||||||
MCPFetcher F(Result);
|
|
||||||
UEdGraphPin* P = F.Walk(Pin).Cast<UEdGraphPin>();
|
|
||||||
if (!P) return;
|
|
||||||
|
|
||||||
Result.Appendf(TEXT("Direction: %s\n"), P->Direction == EGPD_Input ? TEXT("Input") : TEXT("Output"));
|
|
||||||
Result.Appendf(TEXT("Type: %s\n"), *MCPUtils::FormatPinType(P));
|
|
||||||
|
|
||||||
if (P->PinType.IsArray()) Result.Append(TEXT("Container: Array\n"));
|
|
||||||
else if (P->PinType.IsSet()) Result.Append(TEXT("Container: Set\n"));
|
|
||||||
else if (P->PinType.IsMap()) Result.Append(TEXT("Container: Map\n"));
|
|
||||||
|
|
||||||
if (P->PinType.bIsReference) Result.Append(TEXT("IsReference: true\n"));
|
|
||||||
if (P->PinType.bIsConst) Result.Append(TEXT("IsConst: true\n"));
|
|
||||||
|
|
||||||
if (!P->DefaultValue.IsEmpty())
|
|
||||||
Result.Appendf(TEXT("DefaultValue: %s\n"), *P->DefaultValue);
|
|
||||||
if (!P->DefaultTextValue.IsEmpty())
|
|
||||||
Result.Appendf(TEXT("DefaultTextValue: %s\n"), *P->DefaultTextValue.ToString());
|
|
||||||
if (P->DefaultObject)
|
|
||||||
Result.Appendf(TEXT("DefaultObject: %s\n"), *P->DefaultObject->GetPathName());
|
|
||||||
|
|
||||||
// Connected pins
|
|
||||||
for (UEdGraphPin* Linked : P->LinkedTo)
|
|
||||||
{
|
|
||||||
if (!Linked || !Linked->GetOwningNode()) continue;
|
|
||||||
Result.Appendf(TEXT("Connection: %s :: %s\n"),
|
|
||||||
*MCPUtils::FormatName(Linked->GetOwningNode()),
|
|
||||||
*MCPUtils::FormatName(Linked));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "MCPFetcher.h"
|
#include "MCPFetcher.h"
|
||||||
#include "MCPUtils.h"
|
#include "MCPUtils.h"
|
||||||
#include "EdGraph/EdGraphPin.h"
|
#include "EdGraph/EdGraphPin.h"
|
||||||
|
#include "EdGraphSchema_K2.h"
|
||||||
#include "GraphPin_SetDefault.generated.h"
|
#include "GraphPin_SetDefault.generated.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -17,6 +18,9 @@ struct FSetPinDefaultEntry
|
|||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FString Node;
|
||||||
|
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
FString Pin;
|
FString Pin;
|
||||||
|
|
||||||
@@ -31,7 +35,10 @@ class UMCP_GraphPin_SetDefault : public UObject, public IMCPHandler
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(meta=(Description="Array of {pin, value} objects. Pin is a path like /Game/Foo,graph:EventGraph,node:MyNode,pin:InputPin"))
|
UPROPERTY(meta=(Description="Graph path, e.g. /Game/Foo,graph:EventGraph"))
|
||||||
|
FString Graph;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Description="Array of {node, pin, value} objects"))
|
||||||
FMCPJsonArray Pins;
|
FMCPJsonArray Pins;
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
virtual FString GetDescription() const override
|
||||||
@@ -41,18 +48,24 @@ public:
|
|||||||
|
|
||||||
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
||||||
{
|
{
|
||||||
|
// Fetch the graph once.
|
||||||
|
MCPFetcher GraphFetcher(Result);
|
||||||
|
UEdGraph* GraphObj = GraphFetcher.Walk(Graph).Cast<UEdGraph>();
|
||||||
|
if (!GraphObj) return;
|
||||||
|
|
||||||
int32 SuccessCount = 0;
|
int32 SuccessCount = 0;
|
||||||
int32 TotalCount = Pins.Array.Num();
|
int32 TotalCount = Pins.Array.Num();
|
||||||
TSet<UEdGraphNode*> ModifiedNodes;
|
TSet<UEdGraphNode*> ModifiedNodes;
|
||||||
|
|
||||||
|
GraphFetcher.PreEdit();
|
||||||
for (const TSharedPtr<FJsonValue>& PinVal : Pins.Array)
|
for (const TSharedPtr<FJsonValue>& PinVal : Pins.Array)
|
||||||
{
|
{
|
||||||
FSetPinDefaultEntry Entry;
|
FSetPinDefaultEntry Entry;
|
||||||
if (!MCPUtils::PopulateFromJson(FSetPinDefaultEntry::StaticStruct(), &Entry, PinVal, Result))
|
if (!MCPUtils::PopulateFromJson(FSetPinDefaultEntry::StaticStruct(), &Entry, PinVal, Result))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MCPFetcher F(Result);
|
MCPFetcher F(Result, GraphObj);
|
||||||
UEdGraphPin* Pin = F.Walk(Entry.Pin).Cast<UEdGraphPin>();
|
UEdGraphPin* Pin = F.Node(Entry.Node).Pin(Entry.Pin).Cast<UEdGraphPin>();
|
||||||
if (!Pin) continue;
|
if (!Pin) continue;
|
||||||
|
|
||||||
UEdGraphNode* Node = Pin->GetOwningNode();
|
UEdGraphNode* Node = Pin->GetOwningNode();
|
||||||
@@ -63,21 +76,33 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UEdGraphSchema* Schema = Node->GetGraph()->GetSchema();
|
const UEdGraphSchema_K2* Schema = Cast<UEdGraphSchema_K2>(Node->GetGraph()->GetSchema());
|
||||||
if (Schema)
|
check(Schema);
|
||||||
|
|
||||||
|
// Parse and validate the value before applying.
|
||||||
|
FString UseDefaultValue;
|
||||||
|
TObjectPtr<UObject> UseDefaultObject = nullptr;
|
||||||
|
FText UseDefaultText;
|
||||||
|
Schema->GetPinDefaultValuesFromString(Pin->PinType, Node, Entry.Value, UseDefaultValue, UseDefaultObject, UseDefaultText, false);
|
||||||
|
FString Error = Schema->IsPinDefaultValid(Pin, UseDefaultValue, UseDefaultObject, UseDefaultText);
|
||||||
|
if (!Error.IsEmpty())
|
||||||
|
{
|
||||||
|
Result.Appendf(TEXT("error: %s: %s\n"), *MCPUtils::FormatName(Pin), *Error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pin->Modify();
|
||||||
Schema->TrySetDefaultValue(*Pin, Entry.Value);
|
Schema->TrySetDefaultValue(*Pin, Entry.Value);
|
||||||
else
|
|
||||||
Pin->DefaultValue = Entry.Value;
|
|
||||||
|
|
||||||
SuccessCount++;
|
SuccessCount++;
|
||||||
ModifiedNodes.Add(Node);
|
ModifiedNodes.Add(Node);
|
||||||
F.PostEdit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UEdGraphNode* Node : ModifiedNodes)
|
for (UEdGraphNode* Node : ModifiedNodes)
|
||||||
{
|
{
|
||||||
Node->ReconstructNode();
|
Node->ReconstructNode();
|
||||||
}
|
}
|
||||||
|
GraphFetcher.PostEdit();
|
||||||
|
|
||||||
Result.Appendf(TEXT("Set %d/%d pin defaults.\n"), SuccessCount, TotalCount);
|
Result.Appendf(TEXT("Set %d/%d pin defaults.\n"), SuccessCount, TotalCount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "MCPHandler.h"
|
|
||||||
#include "MCPFetcher.h"
|
|
||||||
#include "MCPUtils.h"
|
|
||||||
#include "Materials/Material.h"
|
|
||||||
#include "MaterialDomain.h"
|
|
||||||
#include "Material_DumpProperties.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UMCP_Material_DumpProperties : public UObject, public IMCPHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Material path"))
|
|
||||||
FString Path;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("List top-level material properties such as domain, blend mode, shading model, and usage flags.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
|
||||||
{
|
|
||||||
MCPFetcher F(Result);
|
|
||||||
UMaterial* Mat = F.Asset(Path).Cast<UMaterial>();
|
|
||||||
if (!Mat) return;
|
|
||||||
|
|
||||||
Result.Appendf(TEXT("Material: %s\n"), *MCPUtils::FormatName(Mat));
|
|
||||||
Result.Appendf(TEXT(" domain = %s\n"), *MCPUtils::EnumToString(Mat->MaterialDomain, TEXT("MD_")));
|
|
||||||
Result.Appendf(TEXT(" blendMode = %s\n"), *MCPUtils::EnumToString(Mat->BlendMode, TEXT("BLEND_")));
|
|
||||||
Result.Appendf(TEXT(" shadingModel = %s\n"), *MCPUtils::EnumToString(Mat->GetShadingModels().GetFirstShadingModel(), TEXT("MSM_")));
|
|
||||||
Result.Appendf(TEXT(" opacityMaskClipValue = %g\n"), Mat->OpacityMaskClipValue);
|
|
||||||
Result.Appendf(TEXT(" twoSided = %s\n"), Mat->TwoSided ? TEXT("true") : TEXT("false"));
|
|
||||||
Result.Appendf(TEXT(" bUsedWithSkeletalMesh = %s\n"), Mat->bUsedWithSkeletalMesh ? TEXT("true") : TEXT("false"));
|
|
||||||
Result.Appendf(TEXT(" bUsedWithMorphTargets = %s\n"), Mat->bUsedWithMorphTargets ? TEXT("true") : TEXT("false"));
|
|
||||||
Result.Appendf(TEXT(" bUsedWithNiagaraSprites = %s\n"), Mat->bUsedWithNiagaraSprites ? TEXT("true") : TEXT("false"));
|
|
||||||
Result.Appendf(TEXT(" ditheredLODTransition = %s\n"), Mat->DitheredLODTransition ? TEXT("true") : TEXT("false"));
|
|
||||||
Result.Appendf(TEXT(" bAllowNegativeEmissiveColor = %s\n"), Mat->bAllowNegativeEmissiveColor ? TEXT("true") : TEXT("false"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "MCPHandler.h"
|
|
||||||
#include "MCPFetcher.h"
|
|
||||||
#include "MCPUtils.h"
|
|
||||||
#include "Materials/Material.h"
|
|
||||||
#include "MaterialDomain.h"
|
|
||||||
#include "Material_SetProperty.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UMCP_Material_SetProperty : public UObject, public IMCPHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Material path"))
|
|
||||||
FString Path;
|
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Property name to set (domain, blendMode, twoSided, shadingModel, opacity, opacityMaskClipValue, bUsedWithSkeletalMesh, bUsedWithMorphTargets, bUsedWithNiagaraSprites, ditheredLODTransition, bAllowNegativeEmissiveColor)"))
|
|
||||||
FString Property;
|
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Value to set"))
|
|
||||||
FString Value;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("Set a top-level material property such as domain, blend mode, shading model, or usage flags.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
|
|
||||||
{
|
|
||||||
MCPFetcher F(Result);
|
|
||||||
UMaterial* Mat = F.Asset(Path).Cast<UMaterial>();
|
|
||||||
if (!Mat) return;
|
|
||||||
|
|
||||||
// Parse value and build setter. Validation happens here so we can bail before PreEdit.
|
|
||||||
TFunction<void()> Setter;
|
|
||||||
|
|
||||||
if (Property == TEXT("domain"))
|
|
||||||
{
|
|
||||||
EMaterialDomain NewDomain;
|
|
||||||
if (!MCPUtils::StringToEnum(Value, NewDomain, Result, TEXT("MD_"))) return;
|
|
||||||
Setter = [Mat, NewDomain]() { Mat->MaterialDomain = NewDomain; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("blendMode"))
|
|
||||||
{
|
|
||||||
EBlendMode NewBlend;
|
|
||||||
if (!MCPUtils::StringToEnum(Value, NewBlend, Result, TEXT("BLEND_"))) return;
|
|
||||||
Setter = [Mat, NewBlend]() { Mat->BlendMode = NewBlend; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("shadingModel"))
|
|
||||||
{
|
|
||||||
EMaterialShadingModel NewModel;
|
|
||||||
if (!MCPUtils::StringToEnum(Value, NewModel, Result, TEXT("MSM_"))) return;
|
|
||||||
Setter = [Mat, NewModel]() { Mat->SetShadingModel(NewModel); };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("opacity") || Property == TEXT("opacityMaskClipValue"))
|
|
||||||
{
|
|
||||||
float FloatVal = FCString::Atof(*Value);
|
|
||||||
Setter = [Mat, FloatVal]() { Mat->OpacityMaskClipValue = FloatVal; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("twoSided"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->TwoSided = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("bUsedWithSkeletalMesh"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->bUsedWithSkeletalMesh = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("bUsedWithMorphTargets"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->bUsedWithMorphTargets = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("bUsedWithNiagaraSprites"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->bUsedWithNiagaraSprites = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("ditheredLODTransition") || Property == TEXT("DitheredLODTransition"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->DitheredLODTransition = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else if (Property == TEXT("bAllowNegativeEmissiveColor"))
|
|
||||||
{
|
|
||||||
bool bVal; if (!MCPUtils::StringToBool(Value, bVal, Result)) return;
|
|
||||||
Setter = [Mat, bVal]() { Mat->bAllowNegativeEmissiveColor = bVal ? 1 : 0; };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result.Appendf(TEXT("ERROR: Unknown property '%s'. Valid: domain, blendMode, twoSided, shadingModel, "
|
|
||||||
"opacity, opacityMaskClipValue, bUsedWithSkeletalMesh, bUsedWithMorphTargets, "
|
|
||||||
"bUsedWithNiagaraSprites, ditheredLODTransition, bAllowNegativeEmissiveColor\n"), *Property);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the change between PreEdit/PostEdit.
|
|
||||||
F.PreEdit();
|
|
||||||
Setter();
|
|
||||||
F.PostEdit();
|
|
||||||
MCPUtils::SaveMaterialPackage(Mat);
|
|
||||||
|
|
||||||
Result.Appendf(TEXT("Set %s on %s\n"), *Property, *MCPUtils::FormatName(Mat));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user