第一次提交
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "GGA_K2Node_EffectContextPayload.h"
|
||||
|
||||
#include "BlueprintActionDatabaseRegistrar.h"
|
||||
#include "BlueprintNodeSpawner.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "K2Node_AssignmentStatement.h"
|
||||
#include "K2Node_CallFunction.h"
|
||||
#include "K2Node_TemporaryVariable.h"
|
||||
#include "KismetCompiler.h"
|
||||
#include "Kismet/BlueprintInstancedStructLibrary.h"
|
||||
#include "Utilities/GGA_GameplayEffectFunctionLibrary.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "K2Node"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Node Change events interface implementations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
|
||||
{
|
||||
AllocateDefaultPins();
|
||||
RestoreSplitPins(OldPins);
|
||||
}
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::PostPlacedNewNode()
|
||||
{
|
||||
Super::PostPlacedNewNode();
|
||||
RefreshOutputType();
|
||||
}
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::PinConnectionListChanged(UEdGraphPin* Pin)
|
||||
{
|
||||
Super::PinConnectionListChanged(Pin);
|
||||
|
||||
if (Pin && Pin == GetPayloadTypePin())
|
||||
{
|
||||
RefreshOutputType();
|
||||
}
|
||||
}
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||
{
|
||||
if (Pin == GetPayloadTypePin())
|
||||
{
|
||||
if (Pin->LinkedTo.Num() == 0)
|
||||
{
|
||||
RefreshOutputType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::PostReconstructNode()
|
||||
{
|
||||
Super::PostReconstructNode();
|
||||
RefreshOutputType();
|
||||
}
|
||||
|
||||
void UGGA_K2Node_EffectContextPayload::RefreshOutputType()
|
||||
{
|
||||
UEdGraphPin* OutStructPin = GetOutStructPin();
|
||||
UEdGraphPin* PayloadType = GetPayloadTypePin();
|
||||
|
||||
if (PayloadType->DefaultObject != OutStructPin->PinType.PinSubCategoryObject)
|
||||
{
|
||||
if (OutStructPin->SubPins.Num() > 0)
|
||||
{
|
||||
GetSchema()->RecombinePin(OutStructPin);
|
||||
}
|
||||
|
||||
OutStructPin->PinType.PinSubCategoryObject = PayloadType->DefaultObject;
|
||||
OutStructPin->PinType.PinCategory = (PayloadType->DefaultObject == nullptr) ? UEdGraphSchema_K2::PC_Wildcard : UEdGraphSchema_K2::PC_Struct;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//UK2_Node and EDGraph Interface Implementations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FString UGGA_K2Node_EffectContextPayload::GetPinMetaData(FName InPinName, FName InKey)
|
||||
{
|
||||
FString MetaData = Super::GetPinMetaData(InPinName, InKey);
|
||||
if (MetaData.IsEmpty())
|
||||
{
|
||||
//Filters out the abstract classes from the pin search
|
||||
if (InPinName == GetPayloadTypePin()->GetName() && InKey == FBlueprintMetadata::MD_AllowAbstractClasses)
|
||||
{
|
||||
MetaData = TEXT("false");
|
||||
}
|
||||
}
|
||||
return MetaData;
|
||||
}
|
||||
|
||||
FSlateIcon UGGA_K2Node_EffectContextPayload::GetIconAndTint(FLinearColor& OutColor) const
|
||||
{
|
||||
OutColor = FLinearColor(FColor::Black);
|
||||
return FSlateIcon(FAppStyle::GetAppStyleSetName(), "Kismet.AllClasses.FunctionIcon");
|
||||
}
|
||||
|
||||
|
||||
FLinearColor UGGA_K2Node_EffectContextPayload::GetNodeTitleColor() const
|
||||
{
|
||||
return FLinearColor(FColor::Cyan);
|
||||
}
|
||||
|
||||
|
||||
FText UGGA_K2Node_EffectContextPayload::GetMenuCategory() const
|
||||
{
|
||||
return LOCTEXT("K2Node_GetProperty_Category", "GGA|GameplayEffect|Context");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// PIN GETTERS
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetEffectContextPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::EffectContextPinName);
|
||||
check(Pin->Direction == EGPD_Input);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetInstancedStructPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::InstancedStructPinName);
|
||||
check(Pin->Direction == EGPD_Input);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetKeyPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::KeyPinName);
|
||||
check(Pin->Direction == EGPD_Input);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetPayloadTypePin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::PayloadTypePinName);
|
||||
check(Pin->Direction == EGPD_Input);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetOutStructPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::OutStructPinName);
|
||||
check(Pin->Direction == EGPD_Output);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetValidPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::ValidExecPinName);
|
||||
check(Pin->Direction == EGPD_Output);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
UEdGraphPin* UGGA_K2Node_EffectContextPayload::GetInvalidPin() const
|
||||
{
|
||||
UEdGraphPin* Pin = FindPinChecked(K2Node_ContextPayload_PinNames::InvalidExecPinName);
|
||||
check(Pin->Direction == EGPD_Output);
|
||||
return Pin;
|
||||
}
|
||||
|
||||
|
||||
void UGGA_K2Node_GetEffectContextPayload::AllocateDefaultPins()
|
||||
{
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Struct, FGameplayEffectContextHandle::StaticStruct(), K2Node_ContextPayload_PinNames::EffectContextPinName);
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, UScriptStruct::StaticClass(), K2Node_ContextPayload_PinNames::PayloadTypePinName);
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, K2Node_ContextPayload_PinNames::ValidExecPinName);
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, K2Node_ContextPayload_PinNames::InvalidExecPinName);
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, K2Node_ContextPayload_PinNames::OutStructPinName);
|
||||
|
||||
Super::AllocateDefaultPins();
|
||||
}
|
||||
|
||||
void UGGA_K2Node_GetEffectContextPayload::ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
||||
{
|
||||
Super::ExpandNode(CompilerContext, SourceGraph);
|
||||
|
||||
UFunction* GetValidContextPayloadFunc = UGGA_GameplayEffectFunctionLibrary::StaticClass()->FindFunctionByName(
|
||||
GET_FUNCTION_NAME_CHECKED_ThreeParams(UGGA_GameplayEffectFunctionLibrary, GetValidContextPayload, FGameplayEffectContextHandle, const UScriptStruct*, bool&));
|
||||
UFunction* GetInstStructValueFunc = UBlueprintInstancedStructLibrary::StaticClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UBlueprintInstancedStructLibrary, GetInstancedStructValue));
|
||||
|
||||
if (!GetValidContextPayloadFunc || !GetInstStructValueFunc)
|
||||
{
|
||||
CompilerContext.MessageLog.Error(
|
||||
*LOCTEXT("InvalidClass", "The GetValidContextPayload or GetInstancedStructValue functions have not been found. Check ExpandNode in GGA_K2Node_EffectContextPayload.cpp").ToString(),
|
||||
this);
|
||||
return;
|
||||
}
|
||||
|
||||
const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
|
||||
bool bIsErrorFree = true;
|
||||
|
||||
|
||||
const FEdGraphPinType& PinType = GetOutStructPin()->PinType;
|
||||
|
||||
UK2Node_TemporaryVariable* TempVarOutput = CompilerContext.SpawnInternalVariable(
|
||||
this, PinType.PinCategory, PinType.PinSubCategory, PinType.PinSubCategoryObject.Get(), PinType.ContainerType, PinType.PinValueType);
|
||||
|
||||
UK2Node_AssignmentStatement* AssignNode = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
|
||||
UK2Node_CallFunction* const GetPayloadNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
|
||||
UK2Node_CallFunction* const GetStructValueNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
|
||||
|
||||
GetPayloadNode->SetFromFunction(GetValidContextPayloadFunc);
|
||||
GetStructValueNode->SetFromFunction(GetInstStructValueFunc);
|
||||
|
||||
GetPayloadNode->AllocateDefaultPins();
|
||||
GetStructValueNode->AllocateDefaultPins();
|
||||
AssignNode->AllocateDefaultPins();
|
||||
|
||||
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(GetPayloadNode, this);
|
||||
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(GetStructValueNode, this);
|
||||
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(AssignNode, this);
|
||||
|
||||
//Connect input pins to the GetValidContextPayloadNode
|
||||
//----------------------------------------------------------------------------------------
|
||||
// UEdGraphPin* EffectContextPin = Schema->FindSelfPin(*GetPayloadNode, EGPD_Input);
|
||||
UEdGraphPin* EffectContextPin = GetPayloadNode->FindPinChecked(TEXT("EffectContext"));
|
||||
UEdGraphPin* InterExecLeftPin = GetPayloadNode->GetThenPin();
|
||||
UEdGraphPin* PayloadTypePin = GetPayloadNode->FindPinChecked(TEXT("PayloadType"));
|
||||
UEdGraphPin* InterStructLeftPin = GetPayloadNode->GetReturnValuePin();
|
||||
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetEffectContextPin(), *EffectContextPin).CanSafeConnect();
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetPayloadTypePin(), *PayloadTypePin).CanSafeConnect();
|
||||
//----------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//Connect input Target Pin and the output GetPayloadNode pins to the GetStructValueNode pin
|
||||
//----------------------------------------------------------------------------------------
|
||||
UEdGraphPin* InterExecRightPin = GetStructValueNode->GetExecPin();
|
||||
UEdGraphPin* ValidPin = GetStructValueNode->FindPinChecked(TEXT("Valid"));
|
||||
UEdGraphPin* InvalidPin = GetStructValueNode->FindPinChecked(TEXT("NotValid"));
|
||||
UEdGraphPin* OutStructPin = GetStructValueNode->FindPinChecked(TEXT("Value"));
|
||||
UEdGraphPin* InterStructRightPin = GetStructValueNode->FindPinChecked(TEXT("InstancedStruct"));
|
||||
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *InterExecRightPin).CanSafeConnect();
|
||||
bIsErrorFree &= Schema->TryCreateConnection(InterStructLeftPin, InterStructRightPin);
|
||||
//----------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//Connect the output of GetStructValueNode to the input of Assign node. The Invalid pin directly goes to Invalid pin
|
||||
// but the valid pin goes through the Assign node. The temporary variable is assigned a value, and is connected to the
|
||||
// node's output struct. The order that the connections are made is critical. First the variable needs to connect to the output,
|
||||
// then the variable should be connected to the Variable pin of Assign so the variable type is updated, and only then the Value pin
|
||||
// of Assign can be connected to OutStructPin of the GetStructValueNode.
|
||||
//----------------------------------------------------------------------------------------
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetOutStructPin(), *TempVarOutput->GetVariablePin()).CanSafeConnect();
|
||||
bIsErrorFree &= Schema->TryCreateConnection(AssignNode->GetVariablePin(), TempVarOutput->GetVariablePin());
|
||||
bIsErrorFree &= Schema->TryCreateConnection(AssignNode->GetValuePin(), OutStructPin);
|
||||
|
||||
bIsErrorFree &= Schema->TryCreateConnection(ValidPin, AssignNode->GetExecPin());
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetInvalidPin(), *InvalidPin).CanSafeConnect();
|
||||
bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*GetValidPin(), *AssignNode->GetThenPin()).CanSafeConnect();
|
||||
//----------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
if (!bIsErrorFree)
|
||||
{
|
||||
CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "Get Context Payload: Internal connection error. @@").ToString(), this);
|
||||
}
|
||||
BreakAllNodeLinks();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//UK2_Node and EDGraph Interface Implementations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UGGA_K2Node_GetEffectContextPayload::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
||||
{
|
||||
Super::GetMenuActions(ActionRegistrar);
|
||||
UClass* Action = GetClass();
|
||||
if (ActionRegistrar.IsOpenForRegistration(Action))
|
||||
{
|
||||
UBlueprintNodeSpawner* Spawner = UBlueprintNodeSpawner::Create(GetClass());
|
||||
ActionRegistrar.AddBlueprintAction(Action, Spawner);
|
||||
}
|
||||
}
|
||||
|
||||
FText UGGA_K2Node_GetEffectContextPayload::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return LOCTEXT("K2Node_GetProperty_NodeTitle", "Get Context Payload");
|
||||
}
|
||||
|
||||
FText UGGA_K2Node_GetEffectContextPayload::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("K2Node_GetProperty_TooltipText", "Outputs the context payload based on the selected payload type");
|
||||
}
|
||||
|
||||
FText UGGA_K2Node_GetEffectContextPayload::GetKeywords() const
|
||||
{
|
||||
return LOCTEXT("GetEffectContextPayload", "Get Gameplay Effect Context Payload");
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
Reference in New Issue
Block a user