Files
integration/Plugins/BlueprintMCP/Source/BlueprintMCP/HalfBaked/Blueprint_AddInterface.h
2026-03-18 10:17:58 -04:00

106 lines
3.3 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "WingHandler.h"
#include "WingFetcher.h"
#include "WingUtils.h"
#include "WingServer.h"
#include "Engine/Blueprint.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "UObject/UObjectIterator.h"
#include "Blueprint_AddInterface.generated.h"
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
UCLASS()
class UWing_Blueprint_AddInterface : public UObject, public IWingHandler
{
GENERATED_BODY()
public:
UPROPERTY(meta=(Description="Blueprint package path"))
FString Blueprint;
UPROPERTY(meta=(Description="Native UInterface class name or Blueprint Interface package path"))
FString InterfaceName;
virtual FString GetDescription() const override
{
return TEXT("Add a Blueprint Interface implementation to a Blueprint. "
"Creates stub function graphs for each interface function.");
}
virtual void Handle() override
{
WingFetcher F;
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
if (!BP) return;
// Resolve the interface class
UClass* InterfaceClass = FindInterfaceClass(InterfaceName);
if (!InterfaceClass) return;
// Check for duplicates
for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
{
if (IfaceDesc.Interface == InterfaceClass)
{
UWingServer::Printf(TEXT("ERROR: Interface '%s' is already implemented by this Blueprint.\n"),
*WingUtils::FormatName(InterfaceClass));
return;
}
}
FTopLevelAssetPath InterfacePath = InterfaceClass->GetClassPathName();
bool bAdded = FBlueprintEditorUtils::ImplementNewInterface(BP, InterfacePath);
if (!bAdded)
{
UWingServer::Printf(TEXT("ERROR: ImplementNewInterface failed for '%s'.\n"),
*WingUtils::FormatName(InterfaceClass));
return;
}
// Collect stub function graph names from the newly added interface entry
UWingServer::Printf(TEXT("Added interface %s\n"), *WingUtils::FormatName(InterfaceClass));
UWingServer::Printf(TEXT("Function stubs:\n"));
for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
{
if (IfaceDesc.Interface != InterfaceClass) continue;
for (const UEdGraph* Graph : IfaceDesc.Graphs)
{
if (Graph)
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(Graph));
}
break;
}
}
private:
// Resolve an interface name to a UClass. Tries loaded UInterface classes
// first (for native interfaces), then falls back to loading a Blueprint
// Interface asset by package path.
static UClass* FindInterfaceClass(const FString& Name)
{
// Strategy 1: Search loaded UInterface classes by name
for (TObjectIterator<UClass> It; It; ++It)
{
if (!It->IsChildOf(UInterface::StaticClass())) continue;
if (WingUtils::Identifies(Name, *It))
return *It;
}
// Strategy 2: Try loading as a Blueprint Interface asset by package path
WingFetcher F;
UBlueprint* IfaceBP = F.Asset(Name).Cast<UBlueprint>();
if (IfaceBP && IfaceBP->GeneratedClass && IfaceBP->GeneratedClass->IsChildOf(UInterface::StaticClass()))
return IfaceBP->GeneratedClass;
UWingServer::Printf(TEXT("ERROR: Interface '%s' not found. Provide a native UInterface class name or Blueprint Interface package path.\n"),
*Name);
return nullptr;
}
};