Files
dave jones2 c4107f5283 UE-196156 - Add exec toggle for pure nodes
Blueprint pure nodes were initially intended to be similar to "functional pure". In other words, they're deterministic and produce no side effects (eg: doesn't mutate state). However, pure nodes have violated both conditions for a while now.

Instead, pure nodes are simply function nodes with output values and no visible exec pins. While this can be convenient, they come with a downside: the pure node is evaluated for each connected output. This can lead to unexpected performance issues if the node is expensive to evaluate. In the case of non-deterministic nodes, this can lead to unexpected behavior. In both cases, the user often needs to cull multiple outputs of a pure node and cache the result manually.

The solution here is to add support for toggling purity at the call site. When a function node is placed, right-clicking on it and selecting either "Hide Exec pins" or "Show Exec Pins" will toggle purity. Additionally, the meaning of BlueprintPure and the "Pure" check box changes slightly: it now means that the function node _defaults_ to a pure state when placed in a graph. However, it can be toggled to show its exec pins.

In future changes, we'll also reevaluate which common library functions should continue to default as pure.

#jira UE-196156
#rb dan.oconnor, jodon.karlik, ben.zeigler

[CL 35309072 by dave jones2 in ue5-main branch]
2024-08-05 11:58:15 -04:00

122 lines
3.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "CoreMinimal.h"
#include "EdGraph/EdGraph.h"
#include "EdGraph/EdGraphNode.h"
#include "HAL/PlatformMath.h"
#include "Internationalization/Text.h"
#include "K2Node_CallFunction.h"
#include "Misc/AssertionMacros.h"
#include "UObject/NameTypes.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ObjectPtr.h"
#include "UObject/UObjectGlobals.h"
#include "K2Node_AddComponent.generated.h"
class FArchive;
class UActorComponent;
class UClass;
class UEdGraph;
class UEdGraphPin;
class UObject;
UCLASS(MinimalAPI)
class UK2Node_AddComponent : public UK2Node_CallFunction
{
GENERATED_UCLASS_BODY()
/** Prefix used for component template object name. */
BLUEPRINTGRAPH_API static const FString ComponentTemplateNamePrefix;
UPROPERTY()
uint32 bHasExposedVariable:1;
/** The blueprint name we came from, so we can lookup the template after a paste */
UPROPERTY()
FString TemplateBlueprint;
UPROPERTY()
TObjectPtr<UClass> TemplateType;
//~ Begin UObject Interface
virtual void Serialize(FArchive& Ar) override;
//~ End UObject Interface
//~ Begin UEdGraphNode Interface
virtual void AllocateDefaultPins() override;
virtual void DestroyNode() override;
virtual void PrepareForCopying() override;
virtual void PostPasteNode() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
virtual FString GetDocumentationLink() const override;
virtual FString GetDocumentationExcerptName() const override;
virtual bool IsCompatibleWithGraph(UEdGraph const* Graph) const override;
virtual void ReconstructNode() override;
virtual void FindDiffs(class UEdGraphNode* OtherNode, struct FDiffResults& Results) override;
//~ End UEdGraphNode Interface
//~ Begin K2Node Interface
virtual void PostReconstructNode() override;
virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override;
virtual void ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins) override;
virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
//~ End UK2Node Interface
BLUEPRINTGRAPH_API void AllocateDefaultPinsWithoutExposedVariables();
BLUEPRINTGRAPH_API void AllocatePinsForExposedVariables();
UEdGraphPin* GetTemplateNamePinChecked() const
{
UEdGraphPin* FoundPin = GetTemplateNamePin();
check(FoundPin != NULL);
return FoundPin;
}
UEdGraphPin* GetRelativeTransformPin() const
{
return FindPinChecked(NAME_RelativeTransform);
}
UEdGraphPin* GetManualAttachmentPin() const
{
return FindPinChecked(NAME_ManualAttachment);
}
/** Tries to get a template object from this node. */
BLUEPRINTGRAPH_API UActorComponent* GetTemplateFromNode() const;
/** Helper method used to generate a new, unique component template name. */
FName MakeNewComponentTemplateName(UObject* InOuter, UClass* InComponentClass);
/** Helper method used to instantiate a new component template after duplication. */
BLUEPRINTGRAPH_API void MakeNewComponentTemplate();
/** Static name of function to call */
static BLUEPRINTGRAPH_API FName GetAddComponentFunctionName();
protected:
//~ UK2Node_CallFunction interface
virtual bool CanToggleNodePurity() const override { return false; }
//~ End UK2Node_CallFunction interface
private:
UEdGraphPin* GetTemplateNamePin() const
{
return FindPin(TEXT("TemplateName"));
}
UClass* GetSpawnedType() const;
static const FName NAME_RelativeTransform;
static const FName NAME_ManualAttachment;
};