I have an issue with a Custom Editor Node which extends UK2Node_Switch, bringing that behaviour to Class types. Surely a very useful node to cut down on bloat when dealing with polymorphic types and other such systems. The node compiles correctly, but only ever outputs the default exec pin. Breakpointing doesn’t seem to yield any useful results.
As you can see, our Selection Input pin is a Class (SubCategoryObject UObject::StaticClass), likewise, we also have an Output pin of type Class, and yet we’ve returned a default result.
Perhaps I’m missing the obvious, as I’m new to editor scripting and K2Nodes. Much of the class is inferred from other UK2Node_Switch types. I hope someone here can help with this issue. My suspicion is in the use of PinType.PinCategory = UEdGraphSchema_K2::PC_Class
but as said, I’m new to this. Relevant code is as follows, omitting K2 boilerplate:
UK2Node_SwitchClass .h
class UK2Node_SwitchClass : public UK2Node_Switch
{
GENERATED_UCLASS_BODY()
UPROPERTY(EditAnywhere, Category = PinOptions)
TArray<UClass*> PinClasses;
...
// UK2Node_Switch Interface
virtual void AddPinToSwitchNode() override;
virtual FName GetUniquePinName() override;
virtual FEdGraphPinType GetPinType() const override;
virtual FName GetPinNameGivenIndex(int32 Index) const override;
// End of UK2Node_Switch Interface
protected:
virtual void CreateSelectionPin() override;
virtual void CreateCasePins() override;
virtual void RemovePin(UEdGraphPin* TargetPin) override;
}
UK2Node_SwitchClass .cpp
UK2Node_SwitchClass::UK2Node_SwitchClass(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
FunctionName = TEXT("NotEqual_ClassClass");
FunctionClass = UKismetMathLibrary::StaticClass();
OrphanedPinSaveMode = ESaveOrphanPinMode::SaveNone;
}
void UK2Node_SwitchClass::AddPinToSwitchNode()
{
PinClasses.Add(nullptr);
const FName PinName = GetUniquePinName();
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, PinName);
}
FName UK2Node_SwitchClass::GetUniquePinName()
{
FName NewPinName;
int32 Index = 0;
while (true)
{
NewPinName = *FString::Printf(TEXT("Case_%d"), Index++);
if (!FindPin(NewPinName))
{
break;
}
}
return NewPinName;
}
FEdGraphPinType UK2Node_SwitchClass::GetPinType() const
{
FEdGraphPinType PinType;
PinType.PinCategory = UEdGraphSchema_K2::PC_Class;
PinType.PinSubCategoryObject = UObject::StaticClass();
return PinType;
}
FName UK2Node_SwitchClass::GetPinNameGivenIndex(int32 Index) const
{
return PinClasses.IsValidIndex(Index) ? PinClasses[Index]->GetFName() : "Invalid";
}
void UK2Node_SwitchClass::CreateSelectionPin()
{
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
UEdGraphPin* Pin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Class, UObject::StaticClass(), TEXT("Selection"));
K2Schema->SetPinAutogeneratedDefaultValueBasedOnType(Pin);
}
void UK2Node_SwitchClass::CreateCasePins()
{
for (int32 i = 0; i < PinClasses.Num(); ++i)
{
FName PinName = PinClasses[i] ? PinClasses[i]->GetFName() : GetUniquePinName();
UEdGraphPin* NewPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, PinName);
NewPin->PinFriendlyName = FText::FromName(PinName);
}
}
void UK2Node_SwitchClass::RemovePin(UEdGraphPin* TargetPin)
{
checkSlow(TargetPin);
const FName PinName = TargetPin->PinName;
for (int32 i = 0; i < PinClasses.Num(); ++i)
{
const auto PinClass = PinClasses[i];
if (PinClass->GetFName() == PinName)
{
PinClasses.RemoveAt(i);
break;
}
}
}
UKismetMathLibrary.ini
KISMET_MATH_FORCEINLINE
bool UKismetMathLibrary::NotEqual_ClassClass(class UClass* A, class UClass* B)
{
return A != B;
}