More progress on MCP

This commit is contained in:
2026-03-13 05:34:19 -04:00
parent 303c3fb03a
commit c35cfcd70c
14 changed files with 309 additions and 78 deletions

View File

@@ -330,3 +330,4 @@ MCPFetcher& MCPFetcher::ToGraph()
return TypeMismatch(TEXT("ToGraph"), TEXT("Graph or Material"));
}

View File

@@ -0,0 +1,65 @@
#include "MCPNotifier.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraph.h"
#include "Engine/Blueprint.h"
#include "Materials/Material.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "MaterialEditingLibrary.h"
void MCPNotifier::PreEditAddObject(UObject* Obj)
{
if (!Obj) return;
bool bAlreadyInSet = false;
TouchedSet.Add(Obj, &bAlreadyInSet);
if (bAlreadyInSet) return;
TouchedArray.Add(Obj);
if (bInsidePrePost)
Obj->PreEditChange(nullptr);
}
void MCPNotifier::PreEdit()
{
bInsidePrePost = true;
for (UObject* Obj : TouchedArray)
Obj->PreEditChange(nullptr);
}
void MCPNotifier::PostEdit()
{
TSet<UEdGraphNode*> Nodes;
TSet<UEdGraph*> Graphs;
TSet<UMaterial*> Materials;
TSet<UBlueprint*> Blueprints;
for (int32 i = TouchedArray.Num() - 1; i >= 0; --i)
{
UObject* Obj = TouchedArray[i];
Obj->PostEditChange();
Obj->MarkPackageDirty();
if (UEdGraphNode* Node = ::Cast<UEdGraphNode>(Obj))
Nodes.Add(Node);
if (UEdGraph* Graph = ::Cast<UEdGraph>(Obj))
Graphs.Add(Graph);
if (UBlueprint* BP = ::Cast<UBlueprint>(Obj))
Blueprints.Add(BP);
if (UMaterialInterface* MatIface = ::Cast<UMaterialInterface>(Obj))
if (UMaterial* BaseMat = MatIface->GetMaterial())
Materials.Add(BaseMat);
}
for (UEdGraphNode* Node : Nodes)
Node->ReconstructNode();
for (UEdGraph* Graph : Graphs)
Graph->NotifyGraphChanged();
for (UMaterial *Material : Materials)
UMaterialEditingLibrary::RebuildMaterialInstanceEditors(Material);
for (UBlueprint *Blueprint : Blueprints)
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);
if (GEditor)
GEditor->RedrawAllViewports();
bInsidePrePost = false;
}

View File

@@ -1,18 +1,22 @@
#include "MCPProperty.h"
#include "MCPUtils.h"
#include "Materials/MaterialExpression.h"
#include "MaterialGraph/MaterialGraphNode.h"
MCPProperty::MCPProperty(FProperty* InProp, void* Container)
: Prop(InProp), ValuePtr(InProp ? InProp->ContainerPtrToValuePtr<void>(Container) : nullptr) {}
MCPProperty::MCPProperty(FProperty* InProp, void* InContainer)
: Prop(InProp), Container(InContainer) {}
FString MCPProperty::GetText() const
{
FString Result;
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
Prop->ExportTextItem_Direct(Result, ValuePtr, nullptr, nullptr, PPF_None);
return Result;
}
bool MCPProperty::SetText(const FString& Value, MCPErrorCallback Error)
{
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
const TCHAR* ImportResult = Prop->ImportText_Direct(*Value, ValuePtr, nullptr, PPF_None);
if (!ImportResult)
{
@@ -20,5 +24,78 @@ bool MCPProperty::SetText(const FString& Value, MCPErrorCallback Error)
*Value, *MCPUtils::FormatName(Prop), *Prop->GetCPPType()));
return false;
}
if (Prop->GetOwnerClass()->IsChildOf(UMaterialExpression::StaticClass()))
{
UMaterialExpression* Expr = static_cast<UMaterialExpression*>(Container);
Expr->ForcePropertyValueChanged(Prop);
}
return true;
}
TArray<MCPProperty> MCPProperty::GetAll(UObject* Obj, EPropertyFlags Flags)
{
TArray<MCPProperty> Result;
if (!Obj) return Result;
for (TFieldIterator<FProperty> It(Obj->GetClass()); It; ++It)
{
if (Flags != 0 && !It->HasAnyPropertyFlags(Flags)) continue;
Result.Emplace(*It, Obj);
}
if (UMaterialGraphNode* MatNode = Cast<UMaterialGraphNode>(Obj))
{
if (UMaterialExpression* Expr = MatNode->MaterialExpression)
{
for (TFieldIterator<FProperty> It(Expr->GetClass()); It; ++It)
{
if (Flags != 0 && !It->HasAnyPropertyFlags(Flags)) continue;
Result.Emplace(*It, Expr);
}
}
}
return Result;
}
TArray<MCPProperty> MCPProperty::GetAllSubstring(UObject* Obj, EPropertyFlags Flags, const FString& Substring)
{
TArray<MCPProperty> All = GetAll(Obj, Flags);
if (Substring.IsEmpty()) return All;
TArray<MCPProperty> Result;
for (const MCPProperty& P : All)
{
if (MCPUtils::FormatName(P.Prop).Contains(Substring, ESearchCase::IgnoreCase))
Result.Add(P);
}
return Result;
}
TArray<MCPProperty> MCPProperty::GetAllExactMatch(UObject* Obj, EPropertyFlags Flags, const FString& Name)
{
TArray<MCPProperty> All = GetAll(Obj, Flags);
TArray<MCPProperty> Result;
for (const MCPProperty& P : All)
{
if (MCPUtils::Identifies(Name, P.Prop))
Result.Add(P);
}
return Result;
}
MCPProperty MCPProperty::GetOneExactMatch(UObject* Obj, EPropertyFlags Flags, const FString& Name, MCPErrorCallback Error)
{
TArray<MCPProperty> Matches = GetAllExactMatch(Obj, Flags, Name);
if (Matches.Num() == 0)
{
Error.SetError(FString::Printf(TEXT("Property '%s' not found on %s"),
*Name, *MCPUtils::FormatName(Obj->GetClass())));
return MCPProperty();
}
if (Matches.Num() > 1)
{
Error.SetError(FString::Printf(TEXT("Ambiguous property '%s' on %s"),
*Name, *MCPUtils::FormatName(Obj->GetClass())));
return MCPProperty();
}
return Matches[0];
}

View File

@@ -810,6 +810,7 @@ void MCPUtils::PreEdit(const TArray<UObject*>& Objects)
void MCPUtils::PostEdit(const TArray<UObject*>& Objects)
{
TSet<UEdGraphNode*> Nodes;
TSet<UEdGraph*> Graphs;
TSet<UMaterial*> Materials;
TSet<UBlueprint*> Blueprints;
@@ -819,6 +820,9 @@ void MCPUtils::PostEdit(const TArray<UObject*>& Objects)
Obj->PostEditChange();
Obj->MarkPackageDirty();
if (UEdGraphNode* Node = Cast<UEdGraphNode>(Obj))
Nodes.Add(Node);
if (UEdGraph* Graph = Cast<UEdGraph>(Obj))
Graphs.Add(Graph);
@@ -829,6 +833,8 @@ void MCPUtils::PostEdit(const TArray<UObject*>& Objects)
if (UMaterial* BaseMat = MatIface->GetMaterial())
Materials.Add(BaseMat);
}
for (UEdGraphNode* Node : Nodes)
Node->ReconstructNode();
for (UEdGraph* Graph : Graphs)
Graph->NotifyGraphChanged();
for (UMaterial *Material : Materials)