Files
integration/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPProperty.cpp
2026-03-13 14:26:04 -04:00

103 lines
2.9 KiB
C++

#include "MCPProperty.h"
#include "MCPUtils.h"
#include "MCPServer.h"
#include "Materials/MaterialExpression.h"
#include "MaterialGraph/MaterialGraphNode.h"
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)
{
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
const TCHAR* ImportResult = Prop->ImportText_Direct(*Value, ValuePtr, nullptr, PPF_None);
if (!ImportResult)
{
UMCPServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
*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)
{
TArray<MCPProperty> Matches = GetAllExactMatch(Obj, Flags, Name);
if (Matches.Num() == 0)
{
UMCPServer::Printf(TEXT("ERROR: Property '%s' not found on %s\n"),
*Name, *MCPUtils::FormatName(Obj->GetClass()));
return MCPProperty();
}
if (Matches.Num() > 1)
{
UMCPServer::Printf(TEXT("ERROR: Ambiguous property '%s' on %s\n"),
*Name, *MCPUtils::FormatName(Obj->GetClass()));
return MCPProperty();
}
return Matches[0];
}