// 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; class UAnimGraphNodeBinding; struct FPoseLinkMappingRecord { public: static FPoseLinkMappingRecord MakeFromArrayEntry(UAnimGraphNode_Base* LinkingNode, UAnimGraphNode_Base* LinkedNode, FArrayProperty* ArrayProperty, int32 ArrayIndex) { checkSlow(CastFieldChecked(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 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; UPROPERTY() bool bOnlyUpdateWhenActive = 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 ShowPinForProperties; /** Map from property name->binding info */ UPROPERTY() TMap PropertyBindings_DEPRECATED; /** Properties marked as always dynamic, so they can be set externally */ UPROPERTY() TSet 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", DefaultBindingName="OnInitialUpdate"), DisplayName="On Initial Update") FMemberReference InitialUpdateFunction; // Function called when the node becomes relevant, meaning it goes from having no weight to any weight. UPROPERTY(EditAnywhere, Category = Functions, meta=(FunctionReference, AllowFunctionLibraries, PrototypeFunction="/Script/AnimGraphRuntime.AnimExecutionContextLibrary.Prototype_ThreadSafeAnimUpdateCall", DefaultBindingName="OnBecomeRelevant"), 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", DefaultBindingName="OnUpdate"), DisplayName="On Update") FMemberReference UpdateFunction; private: // Bindings for pins that this node exposes UPROPERTY(EditAnywhere, Instanced, Category=Bindings) TObjectPtr Binding; // 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& OutTaggedMetaData) const override; virtual void AddPinSearchMetaDataInfo(const UEdGraphPin* Pin, TArray& 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& OldPins) override; virtual bool CanCreateUnderSpecifiedSchema(const UEdGraphSchema* DesiredSchema) const override; virtual void GetNodeAttributes(TArray>& 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 HandleFunctionRenamed(UBlueprint* InBlueprint, UClass* InFunctionClass, UEdGraph* InGraph, const FName& InOldFuncName, const FName& InNewFuncName) 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(GetBlueprint()); } // Populate the supplied arrays with the currently reffered to animation assets virtual void GetAllAnimationSequencesReferred(TArray& AnimAssets) const {} // Replace references to animations that exist in the supplied maps virtual void ReplaceReferredAnimations(const TMap& AnimAssetReplacementMap) {}; // Helper function for GetAllAnimationSequencesReferred void HandleAnimReferenceCollection(UAnimationAsset* AnimAsset, TArray& AnimationAssets) const; // Helper function for ReplaceReferredAnimations template void HandleAnimReferenceReplacement(AssetType*& OriginalAsset, const TMap& AnimAssetReplacementMap); template void HandleAnimReferenceReplacement(TObjectPtr& OriginalAsset, const TMap& 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 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& 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 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 NodeType* GetActiveInstanceNode(UObject* AnimInstanceObject) const { if(!AnimInstanceObject) { return nullptr; } if(UAnimBlueprintGeneratedClass* AnimClass = Cast(AnimInstanceObject->GetClass())) { return AnimClass->GetPropertyInstance(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>; // 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& 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 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& /*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 MenuExtender; }; // Make a property binding widget to edit the bindings of the passed-in nodes static TSharedRef 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(); } // 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(); // Gets editor information for all the bound anim node functions (category metadata string, member variable's name) // Used by SAnimGraphNode to display all bound functions of an anim node. virtual void GetBoundFunctionsInfo(TArray> & InOutBindingsInfo); // 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); // Check whether the specified property is bound via PropertyBindings virtual bool HasBinding(FName InPropertyName) const; // Update the property binding name bool RedirectBinding(FName OldPropertyBindingName, FName NewPropertyBindingName); // Get the bindings for this node const UAnimGraphNodeBinding* GetBinding() const { return Binding; } // Get the mutable bindings for this node UAnimGraphNodeBinding* GetMutableBinding() { return Binding; } // Remove any bindings for the specified name void RemoveBindings(FName InBindingName); // 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(); 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; } // 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>& 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* 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* 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; 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; /** Helper function used to validate anim node function references */ void ValidateFunctionRef(FName InPropertyName, const FMemberReference& InRef, const FText& InFunctionName, FCompilerResultsLog& MessageLog); // Create the bindings subobject if required void EnsureBindingsArePresent(); protected: // Old shown pins. Needs to be a member variable to track pin visibility changes between Pre and PostEditChange TArray OldShownPins; }; template void UAnimGraphNode_Base::HandleAnimReferenceReplacement(AssetType*& OriginalAsset, const TMap& AnimAssetReplacementMap) { AssetType* CacheOriginalAsset = OriginalAsset; OriginalAsset = nullptr; if (UAnimationAsset* const* ReplacementAsset = AnimAssetReplacementMap.Find(CacheOriginalAsset)) { OriginalAsset = Cast(*ReplacementAsset); } } template void UAnimGraphNode_Base::HandleAnimReferenceReplacement(TObjectPtr& OriginalAsset, const TMap& AnimAssetReplacementMap) { HandleAnimReferenceReplacement(static_cast(OriginalAsset), AnimAssetReplacementMap); } template TNodeType* UAnimGraphNode_Base::GetDebuggedAnimNode() const { if (UObject* ActiveObject = GetObjectBeingDebugged()) { if (UAnimBlueprintGeneratedClass* Class = Cast((UObject*)ActiveObject->GetClass())) { return Class->GetPropertyInstance(ActiveObject, this); } } return nullptr; }