第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -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