Files
UnrealEngineUWP/Engine/Source/Editor/AnimGraph/Public/AnimGraphNode_Base.h
frederick lupien 63fd57b194 Add a context menu option to unexpose all unused pins in LinkedAnimGraph and LinkedAnimLayer nodes in animation blueprints
This is to be able to quickly hide all pins on linked graph nodes based on animation instance that expose a lot of properties

[REVIEW] [at]Thomas.Sarkanen
#tests PIE
#jira UE-156233
[FYI] [at]Paul.McLaurin

[CL 21908860 by frederick lupien in ue5-main branch]
2022-09-08 20:30:49 -04:00

662 lines
28 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/UnrealType.h"
#include "Animation/AnimationAsset.h"
#include "Animation/AnimBlueprint.h"
#include "Animation/AnimBlueprintGeneratedClass.h"
#include "Animation/AnimNodeBase.h"
#include "Editor.h"
#include "IPropertyAccessEditor.h"
#include "K2Node.h"
#include "Engine/MemberReference.h"
#include "AnimGraphNode_Base.generated.h"
class FAnimGraphNodeDetails;
class FBlueprintActionDatabaseRegistrar;
class FCanvas;
class FCompilerResultsLog;
class FPrimitiveDrawInterface;
class IDetailLayoutBuilder;
class UAnimGraphNode_Base;
class UEdGraphSchema;
class USkeletalMeshComponent;
class IAnimBlueprintGeneratedClassCompiledData;
class IAnimBlueprintCompilationContext;
class IAnimBlueprintCopyTermDefaultsContext;
class IAnimBlueprintNodeCopyTermDefaultsContext;
class IAnimBlueprintNodeOverrideAssetsContext;
class UAnimBlueprintExtension;
struct FPoseLinkMappingRecord
{
public:
static FPoseLinkMappingRecord MakeFromArrayEntry(UAnimGraphNode_Base* LinkingNode, UAnimGraphNode_Base* LinkedNode, FArrayProperty* ArrayProperty, int32 ArrayIndex)
{
checkSlow(CastFieldChecked<FStructProperty>(ArrayProperty->Inner)->Struct->IsChildOf(FPoseLinkBase::StaticStruct()));
FPoseLinkMappingRecord Result;
Result.LinkingNode = LinkingNode;
Result.LinkedNode = LinkedNode;
Result.ChildProperty = ArrayProperty;
Result.ChildPropertyIndex = ArrayIndex;
return Result;
}
static FPoseLinkMappingRecord MakeFromMember(UAnimGraphNode_Base* LinkingNode, UAnimGraphNode_Base* LinkedNode, FStructProperty* MemberProperty)
{
checkSlow(MemberProperty->Struct->IsChildOf(FPoseLinkBase::StaticStruct()));
FPoseLinkMappingRecord Result;
Result.LinkingNode = LinkingNode;
Result.LinkedNode = LinkedNode;
Result.ChildProperty = MemberProperty;
Result.ChildPropertyIndex = INDEX_NONE;
return Result;
}
static FPoseLinkMappingRecord MakeInvalid()
{
FPoseLinkMappingRecord Result;
return Result;
}
bool IsValid() const
{
return LinkedNode != nullptr;
}
UAnimGraphNode_Base* GetLinkedNode() const
{
return LinkedNode;
}
UAnimGraphNode_Base* GetLinkingNode() const
{
return LinkingNode;
}
ANIMGRAPH_API void PatchLinkIndex(uint8* DestinationPtr, int32 LinkID, int32 SourceLinkID) const;
protected:
FPoseLinkMappingRecord()
: LinkedNode(nullptr)
, LinkingNode(nullptr)
, ChildProperty(nullptr)
, ChildPropertyIndex(INDEX_NONE)
{
}
protected:
// Linked node for this pose link, can be nullptr
UAnimGraphNode_Base* LinkedNode;
// Linking node for this pose link, can be nullptr
UAnimGraphNode_Base* LinkingNode;
// Will either be an array property containing FPoseLinkBase derived structs, indexed by ChildPropertyIndex, or a FPoseLinkBase derived struct property
FProperty* ChildProperty;
// Index when ChildProperty is an array
int32 ChildPropertyIndex;
};
UENUM()
enum class EBlueprintUsage : uint8
{
NoProperties,
DoesNotUseBlueprint,
UsesBlueprint
};
/** Enum that indicates level of support of this node for a particular asset class */
enum class EAnimAssetHandlerType : uint8
{
PrimaryHandler,
Supported,
NotSupported
};
/** The type of a property binding */
UENUM()
enum class EAnimGraphNodePropertyBindingType
{
None,
Property,
Function,
};
USTRUCT()
struct FAnimGraphNodePropertyBinding
{
GENERATED_BODY()
FAnimGraphNodePropertyBinding() = default;
/** Pin type */
UPROPERTY()
FEdGraphPinType PinType;
/** Source type if the binding is a promotion */
UPROPERTY()
FEdGraphPinType PromotedPinType;
/** Property binding name */
UPROPERTY()
FName PropertyName = NAME_None;
UPROPERTY()
int32 ArrayIndex = INDEX_NONE;
/** The property path as text */
UPROPERTY()
FText PathAsText;
/** The property path a pin is bound to */
UPROPERTY()
TArray<FString> PropertyPath;
/** The context of the binding */
UPROPERTY()
FName ContextId = NAME_None;
UPROPERTY()
FText CompiledContext;
UPROPERTY()
FText CompiledContextDesc;
/** Whether the binding is a function or not */
UPROPERTY()
EAnimGraphNodePropertyBindingType Type = EAnimGraphNodePropertyBindingType::Property;
/** Whether the pin is bound or not */
UPROPERTY()
bool bIsBound = false;
/** Whether the pin binding is a promotion (e.g. bool->int) */
UPROPERTY()
bool bIsPromotion = false;
};
/**
* This is the base class for any animation graph nodes that generate or consume an animation pose in
* the animation blend graph.
*
* Any concrete implementations will be paired with a runtime graph node derived from FAnimNode_Base
*/
UCLASS(Abstract, BlueprintType)
class ANIMGRAPH_API UAnimGraphNode_Base : public UK2Node
{
GENERATED_UCLASS_BODY()
UPROPERTY(EditAnywhere, Category=PinOptions, EditFixedSize)
TArray<FOptionalPinFromProperty> ShowPinForProperties;
/** Map from property name->binding info */
UPROPERTY(EditAnywhere, Category=PinOptions)
TMap<FName, FAnimGraphNodePropertyBinding> PropertyBindings;
/** Properties marked as always dynamic, so they can be set externally */
UPROPERTY()
TSet<FName> AlwaysDynamicProperties;
UPROPERTY(Transient)
EBlueprintUsage BlueprintUsage;
// Function called before the node is updated for the first time
UPROPERTY(EditAnywhere, Category = Functions, meta=(FunctionReference, AllowFunctionLibraries, PrototypeFunction="/Script/AnimGraphRuntime.AnimExecutionContextLibrary.Prototype_ThreadSafeAnimUpdateCall"), DisplayName="On Initial Update")
FMemberReference InitialUpdateFunction;
// Function called when the node becomes relevant
UPROPERTY(EditAnywhere, Category = Functions, meta=(FunctionReference, AllowFunctionLibraries, PrototypeFunction="/Script/AnimGraphRuntime.AnimExecutionContextLibrary.Prototype_ThreadSafeAnimUpdateCall"), DisplayName="On Become Relevant")
FMemberReference BecomeRelevantFunction;
// Function called when the node is updated
UPROPERTY(EditAnywhere, Category = Functions, meta=(FunctionReference, AllowFunctionLibraries, PrototypeFunction="/Script/AnimGraphRuntime.AnimExecutionContextLibrary.Prototype_ThreadSafeAnimUpdateCall"), DisplayName="On Update")
FMemberReference UpdateFunction;
private:
// Optional reference tag name. If this is set then this node can be referenced from elsewhere in this animation blueprint using an anim node reference
UPROPERTY(EditAnywhere, Category = Tag)
FName Tag;
public:
// UObject interface
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
virtual void PreEditChange(FProperty* PropertyAboutToChange) override;
virtual void PostEditUndo() override;
virtual void Serialize(FArchive& Ar) override;
// End of UObject interface
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FLinearColor GetNodeTitleColor() const override;
virtual FString GetDocumentationLink() const override;
virtual void GetPinHoverText(const UEdGraphPin& Pin, FString& HoverTextOut) const override;
virtual bool ShowPaletteIconOnNode() const override{ return false; }
virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override;
virtual FString GetPinMetaData(FName InPinName, FName InKey) override;
virtual void AddSearchMetaDataInfo(TArray<struct FSearchTagDataPair>& OutTaggedMetaData) const override;
virtual void AddPinSearchMetaDataInfo(const UEdGraphPin* Pin, TArray<struct FSearchTagDataPair>& OutTaggedMetaData) const override;
virtual void PinConnectionListChanged(UEdGraphPin* Pin) override;
virtual void AutowireNewNode(UEdGraphPin* FromPin) override;
virtual void PostPlacedNewNode() override;
virtual void PostPasteNode() override;
virtual void DestroyNode() override;
// End of UEdGraphNode interface
// UK2Node interface
virtual void ReconstructNode() override;
virtual bool NodeCausesStructuralBlueprintChange() const override { return true; }
virtual bool ShouldShowNodeProperties() const override { return true; }
virtual bool CanPlaceBreakpoints() const override { return false; }
virtual void ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins) override;
virtual bool CanCreateUnderSpecifiedSchema(const UEdGraphSchema* DesiredSchema) const override;
virtual void GetNodeAttributes(TArray<TKeyValuePair<FString, FString>>& OutNodeAttributes) const override;
virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override;
virtual FText GetMenuCategory() const override;
virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
// By default return any animation assets we have
virtual UObject* GetJumpTargetForDoubleClick() const override { return GetAnimationAsset(); }
virtual bool CanJumpToDefinition() const override;
virtual void JumpToDefinition() const override;
virtual void HandleVariableRenamed(UBlueprint* InBlueprint, UClass* InVariableClass, UEdGraph* InGraph, const FName& InOldVarName, const FName& InNewVarName) override;
virtual void ReplaceReferences(UBlueprint* InBlueprint, UBlueprint* InReplacementBlueprint, const FMemberReference& InSource, const FMemberReference& InReplacement) override;
virtual bool ReferencesVariable(const FName& InVarName, const UStruct* InScope) const override;
virtual bool ReferencesFunction(const FName& InFunctionName, const UStruct* InScope) const override;
// End of UK2Node interface
// UAnimGraphNode_Base interface
// Whether or not you can add a pose watch on this node
virtual bool IsPoseWatchable() const { return true; }
// Gets the menu category this node belongs in
virtual FString GetNodeCategory() const;
// Is this node a sink that has no pose outputs?
virtual bool IsSinkNode() const { return false; }
// Create any output pins necessary for this node
virtual void CreateOutputPins();
// customize pin data based on the input
virtual void CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const {}
// Gives each visual node a chance to do final validation before it's node is harvested for use at runtime
virtual void ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog);
// Gives each visual node a chance to validate that they are still valid in the context of the compiled class, giving a last shot at error or warning generation after primary compilation is finished
virtual void ValidateAnimNodePostCompile(FCompilerResultsLog& MessageLog, UAnimBlueprintGeneratedClass* CompiledClass, int32 CompiledNodeIndex) {}
// If using CopyPoseFromMesh, the AnimBlueprint Compiler will cache this off for optimizations.
virtual bool UsingCopyPoseFromMesh() const { return false; }
// Gives each visual node a chance to update the node template before it is inserted in the compiled class
virtual void BakeDataDuringCompilation(FCompilerResultsLog& MessageLog) {}
// Give the node a chance to change the display name of a pin
virtual void PostProcessPinName(const UEdGraphPin* Pin, FString& DisplayName) const;
/** Get the animation blueprint to which this node belongs */
UAnimBlueprint* GetAnimBlueprint() const { return CastChecked<UAnimBlueprint>(GetBlueprint()); }
// Populate the supplied arrays with the currently reffered to animation assets
virtual void GetAllAnimationSequencesReferred(TArray<UAnimationAsset*>& AnimAssets) const {}
// Replace references to animations that exist in the supplied maps
virtual void ReplaceReferredAnimations(const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap) {};
// Helper function for GetAllAnimationSequencesReferred
void HandleAnimReferenceCollection(UAnimationAsset* AnimAsset, TArray<UAnimationAsset*>& AnimationAssets) const;
// Helper function for ReplaceReferredAnimations
template<class AssetType>
void HandleAnimReferenceReplacement(AssetType*& OriginalAsset, const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap);
template<class AssetType>
void HandleAnimReferenceReplacement(TObjectPtr<AssetType>& OriginalAsset, const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap);
/**
* Selection notification callback.
* If a node needs to handle viewport input etc. then it should push an editor mode here.
* @param bInIsSelected Whether we selected or deselected the node
* @param InModeTools The mode tools. Use this to push the editor mode if required.
* @param InRuntimeNode The runtime node to go with this skeletal control. This may be NULL in some cases when bInIsSelected is false.
*/
virtual void OnNodeSelected(bool bInIsSelected, class FEditorModeTools& InModeTools, struct FAnimNode_Base* InRuntimeNode);
/** Pose Watch change notification callback. Should be called every time a pose watch on this node is created or destroyed. */
virtual void OnPoseWatchChanged(const bool IsPoseWatchEnabled, TObjectPtr<class UPoseWatch> InPoseWatch, FEditorModeTools& InModeTools, FAnimNode_Base* InRuntimeNode);
/**
* Override this function to push an editor mode when this node is selected
* @return the editor mode to use when this node is selected
*/
virtual FEditorModeID GetEditorMode() const;
// Draw function for supporting visualization
virtual void Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent * PreviewSkelMeshComp) const {}
/**
* Draw function called on nodes that are selected and / or have a pose watch enabled.
* Default implementation calls the basic draw function for selected nodes and does nothing for pose watched nodes. Nodes
* that should render something when a pose watch is enabled but they are not selected should override this function.
*/
virtual void Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, const bool bIsSelected, const bool bIsPoseWatchEnabled) const;
// Canvas draw function to draw to viewport
virtual void DrawCanvas(FViewport& InViewport, FSceneView& View, FCanvas& Canvas, USkeletalMeshComponent * PreviewSkelMeshComp) const {}
// Function to collect strings from nodes to display in the viewport.
// Use this rather than DrawCanvas when adding general text to the viewport.
virtual void GetOnScreenDebugInfo(TArray<FText>& DebugInfo, FAnimNode_Base* RuntimeAnimNode, USkeletalMeshComponent* PreviewSkelMeshComp) const {}
/** Called after editing a default value to update internal node from pin defaults. This is needed for forwarding code to propagate values to preview. */
virtual void CopyPinDefaultsToNodeData(UEdGraphPin* InPin) {}
/** Called to propagate data from the internal node to the preview in Persona. */
virtual void CopyNodeDataToPreviewNode(FAnimNode_Base* InPreviewNode) {}
// BEGIN Interface to support transition getter
// if you return true for DoesSupportExposeTimeForTransitionGetter
// you should implement all below functions
virtual bool DoesSupportTimeForTransitionGetter() const { return false; }
virtual UAnimationAsset* GetAnimationAsset() const { return nullptr; }
virtual TSubclassOf<UAnimationAsset> GetAnimationAssetClass() const { return nullptr; }
virtual const TCHAR* GetTimePropertyName() const { return nullptr; }
virtual UScriptStruct* GetTimePropertyStruct() const { return nullptr; }
// END Interface to support transition getter
// can customize details tab
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder){ }
/** Try to find the preview node instance for this anim graph node */
FAnimNode_Base* FindDebugAnimNode(USkeletalMeshComponent * PreviewSkelMeshComp) const;
template<typename NodeType>
NodeType* GetActiveInstanceNode(UObject* AnimInstanceObject) const
{
if(!AnimInstanceObject)
{
return nullptr;
}
if(UAnimBlueprintGeneratedClass* AnimClass = Cast<UAnimBlueprintGeneratedClass>(AnimInstanceObject->GetClass()))
{
return AnimClass->GetPropertyInstance<NodeType>(AnimInstanceObject, NodeGuid);
}
return nullptr;
}
/**
* Returns whether this node supports the supplied asset class
* @param bPrimaryAssetHandler Is this the 'primary' handler for this asset (the node that should be created when asset is dropped)
*/
virtual EAnimAssetHandlerType SupportsAssetClass(const UClass* AssetClass) const;
// Event that observers can bind to so that they are notified about changes
// made to this node through the property system
DECLARE_EVENT_OneParam(UAnimGraphNode_Base, FOnNodePropertyChangedEvent, FPropertyChangedEvent&);
FOnNodePropertyChangedEvent& OnNodePropertyChanged() { return PropertyChangeEvent; }
// Event that observers can bind to so that they are notified about changes to pin visibility
DECLARE_EVENT_TwoParams(UAnimGraphNode_Base, FPinVisibilityChangedEvent, bool /*bInVisible*/, int32 /*InOptionalPinIndex*/);
FPinVisibilityChangedEvent& OnPinVisibilityChanged() { return PinVisibilityChangedEvent; }
/**
* Helper function to check whether a pin is valid and linked to something else in the graph
* @param InPinName The name of the pin @see UEdGraphNode::FindPin
* @param InPinDirection The direction of the pin we are looking for. If this is EGPD_MAX, all directions are considered
* @return true if the pin is present and connected
*/
bool IsPinExposedAndLinked(const FString& InPinName, const EEdGraphPinDirection Direction = EGPD_MAX) const;
/**
* Helper function to check whether a pin is valid and bound via property access
* @param InPinName The name of the pin @see UEdGraphNode::FindPin
* @param InPinDirection The direction of the pin we are looking for. If this is EGPD_MAX, all directions are considered
* @return true if the pin is present and bound
*/
bool IsPinExposedAndBound(const FString& InPinName, const EEdGraphPinDirection InDirection = EGPD_MAX) const;
/**
* Helper function to check whether a pin is not linked, not bound via property access and still has its default value
* @param InPinName The name of the pin @see UEdGraphNode::FindPin
* @param InPinDirection The direction of the pin we are looking for. If this is EGPD_MAX, all directions are considered
* @return true if the pin is unlinked, unbound and still has its default value
*/
bool IsPinUnlinkedUnboundAndUnset(const FString& InPinName, const EEdGraphPinDirection InDirection) const;
// Event that is broadcast to inform observers that the node title has changed
// The default SAnimationGraphNode uses this to invalidate cached node title text
DECLARE_EVENT(UAnimGraphNode_Base, FOnNodeTitleChangedEvent);
FOnNodeTitleChangedEvent& OnNodeTitleChangedEvent() { return NodeTitleChangedEvent; }
using FNodeAttributeArray = TArray<FName, TInlineAllocator<4>>;
// Get the named attribute types that this node takes (absorbs) as inputs. Other attributes are assumed to 'pass through' this node.
virtual void GetInputLinkAttributes(FNodeAttributeArray& OutAttributes) const {}
// Get the named attribute types that this node provides as outputs. Other attributes are assumed to 'pass through' this node.
virtual void GetOutputLinkAttributes(FNodeAttributeArray& OutAttributes) const {}
// @return wether to show graph attribute icons on pins for this node.
virtual bool ShouldShowAttributesOnPins() const { return true; }
// Some anim graph nodes can act as proxies to outer nodes (e.g. sink nodes in nested graphs).
// Returning that outer node here allows attribute visualization to be forwarded to the inner node from the outer.
// @return the proxy for attribute display
virtual const UAnimGraphNode_Base* GetProxyNodeForAttributes() const { return this; }
// Sets the visibility of the specified pin, reconstructs the node if it changes
void SetPinVisibility(bool bInVisible, int32 InOptionalPinIndex);
// Arguments used to construct a property binding widget
struct FAnimPropertyBindingWidgetArgs
{
FAnimPropertyBindingWidgetArgs(const TArray<UAnimGraphNode_Base*>& InNodes, FProperty* InPinProperty, FName InPinName, FName InBindingName, int32 InOptionalPinIndex)
: Nodes(InNodes)
, PinProperty(InPinProperty)
, PinName(InPinName)
, BindingName(InBindingName)
, OptionalPinIndex(InOptionalPinIndex)
, bOnGraphNode(true)
, bPropertyIsOnFNode(true)
{
}
// The nodes to display the binding for
TArray<UAnimGraphNode_Base*> Nodes;
// The pin property for this binding
FProperty* PinProperty = nullptr;
// The name of the pin
FName PinName = NAME_None;
// The name of the property we are binding to
FName BindingName = NAME_None;
// The optional pin index that refers to this pin
int32 OptionalPinIndex = INDEX_NONE;
// Whether this is for display on a graph node
bool bOnGraphNode = true;
// Whether the property is on the FAnimNode_Base of this anim node
bool bPropertyIsOnFNode = true;
// Delegate used to to access property bindings to modify for the specified node
DECLARE_DELEGATE_TwoParams(FOnGetOptionalPins, UAnimGraphNode_Base* /*InNode*/, TArrayView<FOptionalPinFromProperty>& /*OutOptionalPins*/);
FOnGetOptionalPins OnGetOptionalPins;
// Delegate used to set pin visibility
DECLARE_DELEGATE_ThreeParams(FOnSetPinVisibility, UAnimGraphNode_Base* /*InNode*/, bool /*bInVisible*/, int32 /*InOptionalPinIndex*/);
FOnSetPinVisibility OnSetPinVisibility;
// Menu extender used to add custom entries in the binding menu
TSharedPtr<FExtender> MenuExtender;
};
// Make a property binding widget to edit the bindings of the passed-in nodes
static TSharedRef<SWidget> MakePropertyBindingWidget(const FAnimPropertyBindingWidgetArgs& InArgs);
// Get the property corresponding to a pin. For array element pins returns the outer array property. Returns null if a property cannot be found.
FProperty* GetPinProperty(const UEdGraphPin* InPin) const;
virtual FProperty* GetPinProperty(FName InPinName) const;
// Check whether the named pin is bindable
virtual bool IsPinBindable(const UEdGraphPin* InPin) const;
// Get the tag for this node, if any
FName GetTag() const { return Tag; }
// Set the tag for this node
void SetTag(FName InTag);
// Get the currently-debugged runtime anim node (in the anim BP debugger that this node is currently being edited in)
// @return nullptr if the node cannot be found
FAnimNode_Base* GetDebuggedAnimNode() const { return GetDebuggedAnimNode<FAnimNode_Base>(); }
// Get the currently-debugged runtime anim node of a specified type (in the anim BP debugger that this node is currently being edited in)
// @return nullptr if the node cannot be found
template< typename TNodeType > TNodeType* GetDebuggedAnimNode() const;
// Refreshes the debugged component post-edit.
// This is required to see changes as the component may be either an editor-only component that is not ticking,
// or in a paused PIE world
void PostEditRefreshDebuggedComponent();
// Check if a specified function reference appears to be valid by inspecting only the validity of the name and guid
static bool IsPotentiallyBoundFunction(const FMemberReference& FunctionReference);
protected:
friend class FAnimBlueprintCompilerContext;
friend class FAnimGraphNodeDetails;
friend class UAnimBlueprintExtension;
friend class UAnimBlueprintExtension_Base;
friend class SAnimationGraphNode;
friend class UAnimationGraphSchema;
// Set the tag for this node but without regenerating any BP data for tagging
void SetTagInternal(FName InTag) { Tag = InTag; }
// Gets the animation FNode type represented by this ed graph node
UScriptStruct* GetFNodeType() const;
// Gets the animation FNode property represented by this ed graph node
FStructProperty* GetFNodeProperty() const;
// Get the runtime anim node that we template
FAnimNode_Base* GetFNode();
// Get the extension types that this node type holds on the anim blueprint. Some extension types are always requested by the system
virtual void GetRequiredExtensions(TArray<TSubclassOf<UAnimBlueprintExtension>>& OutExtensions) const {}
// This will be called when a pose link is found, and can be called with PoseProperty being either of:
// - an array property (ArrayIndex >= 0)
// - a single pose property (ArrayIndex == INDEX_NONE)
virtual void CreatePinsForPoseLink(FProperty* PoseProperty, int32 ArrayIndex);
//
virtual FPoseLinkMappingRecord GetLinkIDLocation(const UScriptStruct* NodeType, UEdGraphPin* InputLinkPin);
/** Get the property (and possibly array index) associated with the supplied pin */
virtual void GetPinAssociatedProperty(const UScriptStruct* NodeType, const UEdGraphPin* InputPin, FProperty*& OutProperty, int32& OutIndex) const;
// Process this node's data during compilation
void ProcessDuringCompilation(IAnimBlueprintCompilationContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData);
// Process this node's data during compilation (override point)
virtual void OnProcessDuringCompilation(IAnimBlueprintCompilationContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) {}
// Copy this node's data during the last phase of compilation where term defaults are copied to the new CDO
void CopyTermDefaultsToDefaultObject(IAnimBlueprintCopyTermDefaultsContext& InCompilationContext, IAnimBlueprintNodeCopyTermDefaultsContext& InPerNodeContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData);
// Override point for CopyTermDefaultsToDefaultObject
// Copy this node's data during the last phase of compilation where term defaults are copied to the new CDO
virtual void OnCopyTermDefaultsToDefaultObject(IAnimBlueprintCopyTermDefaultsContext& InCompilationContext, IAnimBlueprintNodeCopyTermDefaultsContext& InPerNodeContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) {}
// Called to override the assets held on a runtime anim node. Implements per-node logic for child anim blueprints.
void OverrideAssets(IAnimBlueprintNodeOverrideAssetsContext& InContext) const;
// Override point for OverrideAssets
virtual void OnOverrideAssets(IAnimBlueprintNodeOverrideAssetsContext& InContext) const {}
// Whether this node should create BP evaluation handlers as part of compilation
virtual bool ShouldCreateStructEvalHandlers() const { return true; }
// Allocates or reallocates pins
void InternalPinCreation(TArray<UEdGraphPin*>* OldPins);
// Override point to create custom pins
// @param OldPins In the case of reconstruction, the OldPins array contains all the pins that the node had prior, otherwise if the
// node is being created anew the array ptr will be null
virtual void CreateCustomPins(TArray<UEdGraphPin*>* OldPins) {}
// Get the pin binding info for the supplied pin
// @param InPinName The name of the pin
// @param OutBindingName The name of the binding that this pin represents (for array pins the binding name includes the array index as e.g. Binding_1)
// @param OutPinProperty The property that the binding represents
// @param OutOptionalPinIndex The optional pin index (index into the ShowPinForProperties array)
// @return false if the pin cannot be bound
virtual bool GetPinBindingInfo(FName InPinName, FName& OutBindingName, FProperty*& OutPinProperty, int32& OutOptionalPinIndex) const;
// Check whether the specified property is bound via PropertyBindings
virtual bool HasBinding(FName InPropertyName) const;
FOnNodePropertyChangedEvent PropertyChangeEvent;
FOnNodeTitleChangedEvent NodeTitleChangedEvent;
FPinVisibilityChangedEvent PinVisibilityChangedEvent;
// Helper function used to refresh the type of a binding
void RecalculateBindingType(FAnimGraphNodePropertyBinding& InBinding);
/** @return the current object being debugged from the blueprint for this node. Can be nullptr. */
UObject* GetObjectBeingDebugged() const;
protected:
// Old shown pins. Needs to be a member variable to track pin visibility changes between Pre and PostEditChange
TArray<FName> OldShownPins;
};
template<class AssetType>
void UAnimGraphNode_Base::HandleAnimReferenceReplacement(AssetType*& OriginalAsset, const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap)
{
AssetType* CacheOriginalAsset = OriginalAsset;
OriginalAsset = nullptr;
if (UAnimationAsset* const* ReplacementAsset = AnimAssetReplacementMap.Find(CacheOriginalAsset))
{
OriginalAsset = Cast<AssetType>(*ReplacementAsset);
}
}
template<class AssetType>
void UAnimGraphNode_Base::HandleAnimReferenceReplacement(TObjectPtr<AssetType>& OriginalAsset, const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap)
{
HandleAnimReferenceReplacement(static_cast<AssetType*&>(OriginalAsset), AnimAssetReplacementMap);
}
template<class TNodeType> TNodeType* UAnimGraphNode_Base::GetDebuggedAnimNode() const
{
if (UObject* ActiveObject = GetObjectBeingDebugged())
{
if (UAnimBlueprintGeneratedClass* Class = Cast<UAnimBlueprintGeneratedClass>((UObject*)ActiveObject->GetClass()))
{
return Class->GetPropertyInstance<TNodeType>(ActiveObject, this);
}
}
return nullptr;
}