Fix wildcard array library functions (Array_Add, Array_RemoveItem, etc)
Real root cause, found after two incorrect attempts: ConnectBlueprintPins
always instantiated the generic UK2Node_CallFunction for every CallFunction
node, including wildcard array library functions like Array_Add and
Array_RemoveItem. Only UK2Node_CallArrayFunction (a UK2Node_CallFunction
subclass) overrides NotifyPinConnectionListChanged to resolve its wildcard
TargetArray/Item pins from the connected array's type -- the generic base
class has a no-op default, so no connection-notification of any kind could
ever have fixed it. This also explains why the ForEachLoop fix (a
MacroInstance, unrelated class hierarchy) worked while this didn't, despite
looking like the same "wildcard pin" symptom.
Debugging trail for the record: first tried NodeConnectionListChanged()
(wrong function, no args -- happened to be irrelevant to both bugs and
coincidentally look like it fixed ForEachLoop). Then tried adding
ReconstructNode() (no effect). Then matched the schema's actual
TryCreateConnection code exactly (PinConnectionListChanged(Pin) with the
specific pin) -- correct in general (this IS what fixes MacroInstance
wildcards, confirmed via UE_LOG marker showing the call executes), but
insufficient here because the node class itself was wrong.
Fix: check TargetFunc->HasMetaData(TEXT("ArrayParm")) (the same meta key
UK2Node_CallArrayFunction itself checks) and instantiate the correct class
before calling SetFromFunction(). Verified: Array_Add's TargetArray/NewItem
pins now show concrete "object/Actor" type instead of wildcard, and the
containing Blueprint compiles.
This commit is contained in:
@@ -51,6 +51,7 @@
|
|||||||
#include "K2Node_DynamicCast.h"
|
#include "K2Node_DynamicCast.h"
|
||||||
#include "K2Node_InputKey.h"
|
#include "K2Node_InputKey.h"
|
||||||
#include "K2Node_SpawnActorFromClass.h"
|
#include "K2Node_SpawnActorFromClass.h"
|
||||||
|
#include "K2Node_CallArrayFunction.h"
|
||||||
#include "EdGraphSchema_K2.h"
|
#include "EdGraphSchema_K2.h"
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
#include "Kismet2/KismetEditorUtilities.h"
|
#include "Kismet2/KismetEditorUtilities.h"
|
||||||
@@ -395,12 +396,32 @@ static UEdGraphNode* CreateBPNodeFromJson(UEdGraph* Graph, UBlueprint* Blueprint
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wildcard array library functions (Array_Add, Array_RemoveItem, etc, tagged with the
|
||||||
|
// "ArrayParm" meta key) need to be instantiated as UK2Node_CallArrayFunction, not the
|
||||||
|
// plain UK2Node_CallFunction -- only that subclass overrides NotifyPinConnectionListChanged
|
||||||
|
// to resolve its wildcard TargetArray/Item pins from the connected array's type. Using the
|
||||||
|
// base class silently produces a node whose wildcard pins never resolve, no matter what
|
||||||
|
// connection-notification is fired afterward.
|
||||||
|
UK2Node_CallFunction* FuncNode = nullptr;
|
||||||
|
if (TargetFunc->HasMetaData(TEXT("ArrayParm")))
|
||||||
|
{
|
||||||
|
FGraphNodeCreator<UK2Node_CallArrayFunction> ArrayCreator(*Graph);
|
||||||
|
UK2Node_CallArrayFunction* ArrayFuncNode = ArrayCreator.CreateNode(false);
|
||||||
|
ArrayFuncNode->SetFromFunction(TargetFunc);
|
||||||
|
ArrayFuncNode->NodePosX = PosX;
|
||||||
|
ArrayFuncNode->NodePosY = PosY;
|
||||||
|
ArrayCreator.Finalize();
|
||||||
|
FuncNode = ArrayFuncNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
FGraphNodeCreator<UK2Node_CallFunction> Creator(*Graph);
|
FGraphNodeCreator<UK2Node_CallFunction> Creator(*Graph);
|
||||||
UK2Node_CallFunction* FuncNode = Creator.CreateNode(false);
|
FuncNode = Creator.CreateNode(false);
|
||||||
FuncNode->SetFromFunction(TargetFunc);
|
FuncNode->SetFromFunction(TargetFunc);
|
||||||
FuncNode->NodePosX = PosX;
|
FuncNode->NodePosX = PosX;
|
||||||
FuncNode->NodePosY = PosY;
|
FuncNode->NodePosY = PosY;
|
||||||
Creator.Finalize();
|
Creator.Finalize();
|
||||||
|
}
|
||||||
NewNode = FuncNode;
|
NewNode = FuncNode;
|
||||||
}
|
}
|
||||||
else if (NodeType == TEXT("Event"))
|
else if (NodeType == TEXT("Event"))
|
||||||
@@ -791,11 +812,14 @@ FString UMCPythonHelper::ConnectBlueprintPins(UBlueprint* Blueprint, const FStri
|
|||||||
SourcePin->MakeLinkTo(TargetPin);
|
SourcePin->MakeLinkTo(TargetPin);
|
||||||
|
|
||||||
// Notify both nodes so wildcard pins (e.g. MacroInstance nodes like ForEachLoop, or
|
// Notify both nodes so wildcard pins (e.g. MacroInstance nodes like ForEachLoop, or
|
||||||
// wildcard array library calls) can resolve their type from the new connection. The
|
// wildcard array library calls like Array_Add/Array_RemoveItem) can resolve their type
|
||||||
// real graph editor does this via the schema's TryCreateConnection; MakeLinkTo alone
|
// from the new connection. This mirrors exactly what UEdGraphSchema::TryCreateConnection
|
||||||
// doesn't trigger it, so wildcard-typed pins were silently left unresolved.
|
// does after MakeLinkTo (see EdGraphSchema.cpp) -- MakeLinkTo alone doesn't trigger it,
|
||||||
SourceNode->NodeConnectionListChanged();
|
// so wildcard-typed pins were silently left unresolved. Must pass the specific pin, not
|
||||||
TargetNode->NodeConnectionListChanged();
|
// a bare no-arg notification: PinConnectionListChanged(Pin) is what K2Node subclasses
|
||||||
|
// (e.g. K2Node_CallArrayFunction::NotifyPinConnectionListChanged) actually key off of.
|
||||||
|
SourcePin->GetOwningNode()->PinConnectionListChanged(SourcePin);
|
||||||
|
TargetPin->GetOwningNode()->PinConnectionListChanged(TargetPin);
|
||||||
|
|
||||||
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
||||||
return MakeJsonSuccess(FString::Printf(TEXT("Connected %s.%s -> %s.%s"),
|
return MakeJsonSuccess(FString::Printf(TEXT("Connected %s.%s -> %s.%s"),
|
||||||
|
|||||||
Reference in New Issue
Block a user