Files
integration/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/Handlers/UMCPHandler_RemoveBlueprintComponent.h

97 lines
2.9 KiB
C
Raw Normal View History

2026-03-08 22:17:14 -04:00
#pragma once
#include "CoreMinimal.h"
#include "MCPHandler.h"
2026-03-10 07:17:42 -04:00
#include "MCPFetcher.h"
2026-03-08 22:17:14 -04:00
#include "MCPUtils.h"
#include "Engine/Blueprint.h"
#include "Engine/SimpleConstructionScript.h"
#include "Engine/SCS_Node.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "UMCPHandler_RemoveBlueprintComponent.generated.h"
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
2026-03-11 22:03:32 -04:00
UCLASS(meta=(Group="Unclassified"))
2026-03-08 22:17:14 -04:00
class UMCPHandler_RemoveBlueprintComponent : public UObject, public IMCPHandler
{
GENERATED_BODY()
public:
UPROPERTY(meta=(Description="Blueprint name or package path"))
FString Blueprint;
UPROPERTY(meta=(Description="Component to remove"))
FString Component;
virtual FString GetDescription() const override
{
return TEXT("Remove a component from a Blueprint's SimpleConstructionScript.");
}
2026-03-10 07:17:42 -04:00
virtual void Handle(const FJsonObject* Json, FStringBuilderBase& Result) override
2026-03-08 22:17:14 -04:00
{
2026-03-10 07:17:42 -04:00
MCPFetcher F(Result);
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
if (!BP) return;
2026-03-08 22:17:14 -04:00
USimpleConstructionScript* SCS = BP->SimpleConstructionScript;
if (!SCS)
{
2026-03-10 07:17:42 -04:00
Result.Append(TEXT("ERROR: Not an Actor Blueprint (no SimpleConstructionScript).\n"));
return;
2026-03-08 22:17:14 -04:00
}
2026-03-10 07:17:42 -04:00
// Find the node to remove using Identifies for consistent name matching
2026-03-08 22:17:14 -04:00
USCS_Node* NodeToRemove = nullptr;
const TArray<USCS_Node*>& AllNodes = SCS->GetAllNodes();
for (USCS_Node* Node : AllNodes)
{
2026-03-10 07:17:42 -04:00
if (Node && Node->ComponentTemplate &&
MCPUtils::Identifies(Component, Node->ComponentTemplate))
2026-03-08 22:17:14 -04:00
{
NodeToRemove = Node;
break;
}
}
if (!NodeToRemove)
{
2026-03-10 07:17:42 -04:00
Result.Appendf(TEXT("ERROR: Component '%s' not found.\nAvailable components:\n"),
*Component);
2026-03-08 22:17:14 -04:00
for (USCS_Node* Node : AllNodes)
{
2026-03-10 07:17:42 -04:00
if (Node && Node->ComponentTemplate)
Result.Appendf(TEXT(" %s\n"), *MCPUtils::FormatName(Node->ComponentTemplate));
2026-03-08 22:17:14 -04:00
}
return;
}
// Prevent removing the root scene component if it has children
const TArray<USCS_Node*>& RootNodes = SCS->GetRootNodes();
if (RootNodes.Contains(NodeToRemove) && NodeToRemove->GetChildNodes().Num() > 0)
{
2026-03-10 07:17:42 -04:00
Result.Appendf(TEXT("ERROR: Cannot remove '%s' — it is a root component with %d child(ren). "
"Remove or re-parent the children first.\n"),
*MCPUtils::FormatName(NodeToRemove->ComponentTemplate),
NodeToRemove->GetChildNodes().Num());
return;
2026-03-08 22:17:14 -04:00
}
2026-03-10 07:17:42 -04:00
FString RemovedName = MCPUtils::FormatName(NodeToRemove->ComponentTemplate);
2026-03-08 22:17:14 -04:00
// Remove the node (promotes children to parent if it has any — but we've guarded root above)
SCS->RemoveNodeAndPromoteChildren(NodeToRemove);
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(BP);
bool bSaved = MCPUtils::SaveBlueprintPackage(BP);
2026-03-10 07:17:42 -04:00
Result.Appendf(TEXT("Removed component %s.%s\n"),
*RemovedName,
bSaved ? TEXT("") : TEXT(" WARNING: save failed."));
2026-03-08 22:17:14 -04:00
}
};