1
0
KF2-Dev-Scripts/Engine/Classes/AnimNode.uc
2020-12-13 18:01:13 +03:00

285 lines
13 KiB
Ucode

/**
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class AnimNode extends AnimObject
native(Anim)
hidecategories(Object)
abstract;
/** Enumeration for slider types */
enum ESliderType
{
ST_1D,
ST_2D
};
/** Curve Key
@CurveName : Morph Target name to blend
@Weight : Weight of the Morph Target
**/
struct CurveKey
{
var name CurveName;
var float Weight;
};
/** This node is considered 'relevant' - that is, has >0 weight in the final blend. */
var transient const bool bRelevant;
/** set to TRUE when this node became relevant this round of updates. Will be set to false on the next tick. */
var transient const bool bJustBecameRelevant;
/** If TRUE, this node will be ticked, even if bPauseAnims is TRUE on the SkelMeshComp. */
var(Performance) bool bTickDuringPausedAnims;
/** This node is editor only and used for something like placement preview */
var const bool bEditorOnly;
/** Used to avoid ticking a node twice if it has multiple parents. */
var transient const int NodeTickTag;
/** Initialization tag, for deferred InitAnim. */
var transient const INT NodeInitTag;
/** Used to avoid a node triggerring event twice if it has multiple parents. */
var transient const int NodeEndEventTick;
/** Index in AnimTick Array. Serialized, because we serialize TickArrayIndex in UAnimTree. */
var const int TickArrayIndex;
/** Used to indicate whether the BoneAtom cache for this node is up-to-date or not. */
var transient const int NodeCachedAtomsTag;
/** Total apparent weight this node has in the final blend of all animations. */
var const float NodeTotalWeight;
/** Array of Parent nodes, which in most cases only has 1 element. */
var duplicatetransient Array<AnimNodeBlendBase> ParentNodes;
/** This is the name used to find an AnimNode by name from a tree. */
var() name NodeName;
/** Temporarily disable caching when calling Super::GetBoneAtoms so it's not done multiple times. */
var const transient bool bDisableCaching;
/** If a node is linked to more than once in the graph, this is a cache of the results, to avoid re-evaluating the results. */
var transient array<BoneAtom> CachedBoneAtoms;
/** Num Desired Bones used in CachedBoneAtoms. If we request something different, CachedBoneAtoms array is not going to be valid. */
var transient byte CachedNumDesiredBones;
/** Cached root motion delta, to avoid recalculating (see above). */
var transient BoneAtom CachedRootMotionDelta;
/** Cached bool indicating if node supplies root motion, to avoid recalculating (see above). */
var transient int bCachedHasRootMotion;
/** Cached curve keys to avoid recalculating (see above). */
var transient array<CurveKey> CachedCurveKeys;
/** used when iterating over nodes via GetNodes() and related functions to skip nodes that have already been processed */
var transient int SearchTag;
/** Array of blended curve key for editor only **/
var(Morph) editoronly editconst transient array<CurveKey> LastUpdatedAnimMorphKeys;
/** Flags to control if Script Events should be called. Note that those will affect performance, so be careful! */
var() bool bCallScriptEventOnInit;
var() bool bCallScriptEventOnBecomeRelevant;
var() bool bCallScriptEventOnCeaseRelevant;
cpptext
{
UAnimNode * GetAnimNode() { return this;}
// UAnimNode interface
/** Do any initialisation, and then call InitAnim on all children. Should not discard any existing anim state though. */
virtual void InitAnim( USkeletalMeshComponent* meshComp, UAnimNodeBlendBase* Parent );
/** Deferred Initialization, called only when the node is relevant in the tree. */
virtual void DeferredInitAnim() {}
/** Call DeferredInitAnim() if the node required it. Recurses through the Tree. Increase UAnimNode::CurrentSeachTag before calling. */
virtual void CallDeferredInitAnim();
/** AnimSets have been updated, update all animations */
virtual void AnimSetsUpdated() {}
/**
* Called just after a node has been copied from its AnimTreeTemplate version.
* This is called on the copy, and SourceNode is the node within the AnimTreeTemplate.
*/
virtual void PostAnimNodeInstance(UAnimNode* SourceNode, TMap<UAnimNode*,UAnimNode*>& SrcToDestNodeMap) {}
/**
* Called when we need to reset our values to the source. This is called on a node that already has all pointers set up correctly
*/
virtual void ResetAnimNodeToSource(UAnimNode *SourceNode);
/**
* Update this node, then call TickAnim on all children.
* @param DeltaSeconds Amount of time to advance this node.
* @param TotalWeight The eventual weight that this node will have in the final blend. This is the multiplication of weights of all nodes above this one.
*/
virtual void TickAnim(FLOAT DeltaSeconds) {}
/** Parent node is requesting a blend out. Give node a chance to delay that. */
virtual UBOOL CanBlendOutFrom() { return TRUE; }
/** parent node is requesting a blend in. Give node a chance to delay that. */
virtual UBOOL CanBlendTo() { return TRUE; }
/**
* Add this node and all children to array. Node are added so a parent is always before its children in the array.
* @param bForceTraversal Disables optimization when calling this from the root. (precached AnimTickArray returned).
*/
void GetNodes(TArray<UAnimNode*>& Nodes, bool bForceTraversal=FALSE);
/** Add this node and all children of the specified class to array. Node are added so a parent is always before its children in the array. */
void GetNodesByClass(TArray<class UAnimNode*>& Nodes, class UClass* BaseClass);
/** Return an array with all UAnimNodeSequence childs, including this node. */
void GetAnimSeqNodes(TArray<UAnimNodeSequence*>& Nodes, FName InSynchGroupName=NAME_None);
virtual void BuildParentNodesArray();
/** Used for building array of AnimNodes in 'tick' order - that is, all parents of a node are added to array before it. */
virtual void BuildTickArray(TArray<UAnimNode*>& OutTickArray) {}
/**
* Get the local transform for each bone. If a blend, will recursively ask children and blend etc.
* DesiredBones should be in strictly increasing order.
*/
virtual void GetBoneAtoms(FBoneAtomArray& Atoms, const TArray<BYTE>& DesiredBones, FBoneAtom& RootMotionDelta, INT& bHasRootMotion, FCurveKeyArray& CurveKeys);
/**
* Will copy the cached results into the OutAtoms array if they are up to date and return TRUE
* If cache is not up to date, does nothing and retuns FALSE.
*/
virtual UBOOL GetCachedResults(FBoneAtomArray& OutAtoms, FBoneAtom& OutRootMotionDelta, INT& bOutHasRootMotion, FCurveKeyArray& OutCurveKeys, INT NumDesiredBones);
/** Save the supplied array of BoneAtoms in the CachedBoneAtoms. */
virtual UBOOL ShouldSaveCachedResults();
void SaveCachedResults(const FBoneAtomArray& NewAtoms, const FBoneAtom& NewRootMotionDelta, INT bNewHasRootMotion, const FCurveKeyArray& NewCurveKeys, INT NumDesiredBones);
/**
* Whether we should keep the cached result for the next frame or not
* This is to avoid keeping cached result once it ticks.
* It will release cache result if this returns FALSE
**/
virtual UBOOL ShouldKeepCachedResult() { return FALSE; }
/**
* Clear Cached Result
**/
virtual void ClearCachedResult();
/** Get notification that this node has become relevant for the final blend. ie TotalWeight is now > 0 */
virtual void OnBecomeRelevant();
/** Get notification that this node is no longer relevant for the final blend. ie TotalWeight is now == 0 */
virtual void OnCeaseRelevant();
/** Utility for counting the number of parents of this node that have been ticked. */
UBOOL WereAllParentsTicked() const;
/** Returns TRUE if this node is a child of Node */
UBOOL IsChildOf(UAnimNode* Node);
/** Returns TRUE if this node is a child of Node */
UBOOL IsChildOf_Internal(UAnimNode* Node);
/** Optimisation way to see if this is a UAnimTree */
virtual UAnimTree* GetAnimTree() { return NULL; }
virtual void SetAnim( FName SequenceName ) {}
virtual void SetPosition( FLOAT NewTime, UBOOL bFireNotifies ) {}
/** Override these functions to disable loading of editor only nodes */
virtual UBOOL NeedsLoadForClient() const;
virtual UBOOL NeedsLoadForServer() const;
/// ANIMTREE EDITOR
/**
* Draws this node in the AnimTreeEditor.
*
* @param Canvas The canvas to use.
* @param SelectedNodes Reference to array of all currently selected nodes, potentially including this node
* @param bShowWeight If TRUE, show the global percentage weight of this node, if applicable.
*/
virtual void DrawNode(FCanvas* Canvas, const TArray<UAnimObject*>& SelectedNodes, UBOOL bShowWeight) { DrawAnimNode(Canvas, SelectedNodes, bShowWeight); }
/**
* Draws this anim node in the AnimTreeEditor.
*
* @param Canvas The canvas to use.
* @param SelectedNodes Reference to array of all currently selected nodes, potentially including this node
* @param bShowWeight If TRUE, show the global percentage weight of this node, if applicable.
*/
virtual void DrawAnimNode(FCanvas* Canvas, const TArray<UAnimObject*>& SelectedNodes, UBOOL bShowWeight) {}
/** Return title to display for this Node in the AnimTree editor. */
virtual FString GetNodeTitle() { return TEXT(""); }
/** For editor use. */
virtual FIntPoint GetConnectionLocation(INT ConnType, int ConnIndex);
/** Return the number of sliders */
virtual INT GetNumSliders() const { return 0; }
/** Return the slider type of slider Index */
virtual ESliderType GetSliderType(INT InIndex) const { return ST_1D; }
/** Return current position of slider for this node in the AnimTreeEditor. Return value should be within 0.0 to 1.0 range. */
virtual FLOAT GetSliderPosition(INT SliderIndex, INT ValueIndex) { return 0.f; }
/** Called when slider is moved in the AnimTreeEditor. NewSliderValue is in range 0.0 to 1.0. */
virtual void HandleSliderMove(INT SliderIndex, INT ValueIndex, FLOAT NewSliderValue) {}
/** Get the number to draw under the slider to show the current value being previewed. */
virtual FString GetSliderDrawValue(INT SliderIndex) { return FString(TEXT("")); }
/** internal code for GetNodes(); should only be called from GetNodes() or from the GetNodesInternal() of this node's parent */
virtual void GetNodesInternal(TArray<UAnimNode*>& Nodes);
/** Called after (copy/)pasted - reset values or re-link if needed**/
virtual void OnPaste();
// STATIC ANIMTREE UTILS
/** flag to prevent calling GetNodesInternal() from anywhere besides GetNodes() or another GetNodesInternal(), since
* we can't make it private/protected because UAnimNodeBlendBase needs to be able to call it on its children
*/
static UBOOL bNodeSearching;
/** current tag value used for SearchTag on nodes being iterated over. Incremented every time a new search is started */
static INT CurrentSearchTag;
/** Array to keep track of those nodes requiring an actual clear of the cache */
static TArray<UAnimNode*> NodesRequiringCacheClear;
/**
* Fills the Atoms array with the specified skeletal mesh reference pose.
*
* @param Atoms [out] Output array of relative bone transforms. Must be the same length as RefSkel when calling function.
* @param DesiredBones Indices of bones we want to modify. Parents must occur before children.
* @param RefSkel Input reference skeleton to create atoms from.
*/
static void FillWithRefPose(TArray<FBoneAtom>& Atoms, const TArray<BYTE>& DesiredBones, const TArray<struct FMeshBone>& RefSkel);
static void FillWithRefPose(FBoneAtomArray& Atoms, const TArray<BYTE>& DesiredBones, const TArray<struct FMeshBone>& RefSkel);
/** Utility for taking an array of bone indices and ensuring that all parents are present (ie. all bones between those in the array and the root are present). */
static void EnsureParentsPresent( TArray<BYTE>& BoneIndices, USkeletalMesh* SkelMesh );
/** Utility functions to ease off Casting */
virtual class UAnimNodeSlot* GetAnimNodeSlot() { return NULL; }
virtual class UAnimNodeAimOffset* GetAnimNodeAimOffset() { return NULL; }
virtual class UAnimNodeSequence* GetAnimNodeSequence() { return NULL; }
}
/** Called from InitAnim. Allows initialization of script-side properties of this node. */
event OnInit();
/** Get notification that this node has become relevant for the final blend. ie TotalWeight is now > 0 */
event OnBecomeRelevant();
/** Get notification that this node is no longer relevant for the final blend. ie TotalWeight is now == 0 */
event OnCeaseRelevant();
/**
* Find an Animation Node in the Animation Tree whose NodeName matches InNodeName.
* Will search this node and all below it.
* Warning: The search is O(n^2), so for large AnimTrees, cache result.
*/
native final function AnimNode FindAnimNode(name InNodeName);
native function PlayAnim(bool bLoop = false, float Rate = 1.0f, float StartTime = 0.0f);
native function StopAnim();
// calls PlayAnim with the current settings
native function ReplayAnim();