Files
integration/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/Handlers/Deprecated/UMCPHandler_DisconnectMaterialExpressionPin.h
2026-03-11 22:03:32 -04:00

99 lines
3.2 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "MCPHandler.h"
#include "MCPAssetFinder.h"
#include "MCPFetcher.h"
#include "MCPUtils.h"
#include "Materials/Material.h"
#include "Materials/MaterialExpression.h"
#include "Materials/MaterialFunction.h"
#include "MaterialGraph/MaterialGraph.h"
#include "EdGraph/EdGraph.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraphPin.h"
#include "UMCPHandler_DisconnectMaterialExpressionPin.generated.h"
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
UCLASS(meta=(Group="Unclassified"))
class UMCPHandler_DisconnectMaterialExpressionPin : public UObject, public IMCPHandler
{
GENERATED_BODY()
public:
UPROPERTY(meta=(Optional, Description="Material name or package path (specify this or materialFunction)"))
FString Material;
UPROPERTY(meta=(Optional, Description="Material function name or package path (specify this or material)"))
FString MaterialFunction;
UPROPERTY(meta=(Description="Node name (use FormatName-style identifier)"))
FString Node;
UPROPERTY(meta=(Description="Pin name to disconnect"))
FString PinName;
virtual FString GetDescription() const override
{
return TEXT("Break all connections on a specific pin in a material or material function graph.");
}
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
{
if (Material.IsEmpty() && MaterialFunction.IsEmpty())
{
Result.Append(TEXT("ERROR: Specify 'material' or 'materialFunction'.\n"));
return;
}
// Load material or material function
UMaterial* MaterialObj = nullptr;
UMaterialFunction* MatFunc = nullptr;
if (!MaterialFunction.IsEmpty())
{
MCPAssets<UMaterialFunction> Assets;
if (!Assets.Exact(MaterialFunction).Errors(Result).ENone().ETwo().Load()) return;
MatFunc = Assets.Object();
}
else
{
MCPAssets<UMaterial> Assets;
if (!Assets.Exact(Material).Errors(Result).ENone().ETwo().Load()) return;
MaterialObj = Assets.Object();
}
if (MaterialObj) MCPUtils::EnsureMaterialGraph(MaterialObj);
UEdGraph* Graph = MaterialObj ? (UEdGraph*)MaterialObj->MaterialGraph : (MatFunc ? MatFunc->MaterialGraph : nullptr);
if (!Graph)
{
Result.Appendf(TEXT("ERROR: %s has no material graph.\n"),
MaterialObj ? *MCPUtils::FormatName(MaterialObj) : *MCPUtils::FormatName(MatFunc));
return;
}
// Find node and pin via MCPFetcher
MCPFetcher F(Result, Graph);
UEdGraphPin* Pin = F.Node(Node).Pin(PinName).Cast<UEdGraphPin>();
if (!Pin) return;
int32 BrokenCount = Pin->LinkedTo.Num();
Pin->BreakAllPinLinks();
UObject* Asset = MaterialObj ? (UObject*)MaterialObj : (UObject*)MatFunc;
Asset->PreEditChange(nullptr);
Asset->PostEditChange();
bool bSaved = MaterialObj ? MCPUtils::SaveMaterialPackage(MaterialObj) : MCPUtils::SaveGenericPackage(MatFunc);
Result.Appendf(TEXT("Disconnected %d link(s) from %s on %s.\n"),
BrokenCount, *MCPUtils::FormatName(Pin), *MCPUtils::FormatName(Pin->GetOwningNode()));
if (!bSaved)
Result.Append(TEXT("WARNING: Failed to save package.\n"));
}
};