296 lines
9.5 KiB
C++
296 lines
9.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "BonePose.h"
|
|
#include "BoneControllers/AnimNode_ModifyBone.h"
|
|
#include "Animation/AnimSingleNodeInstance.h"
|
|
#include "Animation/AnimSingleNodeInstanceProxy.h"
|
|
#include "AnimNodes/AnimNode_CurveSource.h"
|
|
#include "AnimNodes/AnimNode_PoseBlendNode.h"
|
|
#include "AnimNodes/AnimNode_CopyPoseFromMesh.h"
|
|
#include "AnimPreviewInstance.generated.h"
|
|
|
|
/** Enum to know how montage is being played */
|
|
UENUM()
|
|
enum EMontagePreviewType : int
|
|
{
|
|
/** Playing montage in usual way. */
|
|
EMPT_Normal,
|
|
/** Playing all sections. */
|
|
EMPT_AllSections,
|
|
EMPT_MAX,
|
|
};
|
|
|
|
|
|
/** Proxy override for this UAnimInstance-derived class */
|
|
USTRUCT()
|
|
struct ANIMGRAPH_API FAnimPreviewInstanceProxy : public FAnimSingleNodeInstanceProxy
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
FAnimPreviewInstanceProxy()
|
|
{
|
|
bCanProcessAdditiveAnimations = true;
|
|
}
|
|
|
|
FAnimPreviewInstanceProxy(UAnimInstance* InAnimInstance)
|
|
: FAnimSingleNodeInstanceProxy(InAnimInstance)
|
|
, SkeletalControlAlpha(1.0f)
|
|
, bEnableControllers(true)
|
|
, bSetKey(false)
|
|
{
|
|
bCanProcessAdditiveAnimations = true;
|
|
}
|
|
|
|
virtual void Initialize(UAnimInstance* InAnimInstance) override;
|
|
virtual void Update(float DeltaSeconds) override;
|
|
virtual void UpdateAnimationNode(const FAnimationUpdateContext& InContext) override;
|
|
virtual bool Evaluate(FPoseContext& Output) override;
|
|
virtual void PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds) override;
|
|
virtual void SetAnimationAsset(UAnimationAsset* NewAsset, USkeletalMeshComponent* MeshComponent, bool bIsLooping, float InPlayRate) override;
|
|
|
|
void ResetModifiedBone(bool bCurveController = false);
|
|
|
|
FAnimNode_ModifyBone* FindModifiedBone(const FName& InBoneName, bool bCurveController = false);
|
|
|
|
FAnimNode_ModifyBone& ModifyBone(const FName& InBoneName, bool bCurveController = false);
|
|
|
|
void RemoveBoneModification(const FName& InBoneName, bool bCurveController = false);
|
|
|
|
void EnableControllers(bool bEnable)
|
|
{
|
|
bEnableControllers = bEnable;
|
|
}
|
|
|
|
void SetSkeletalControlAlpha(float InSkeletalControlAlpha)
|
|
{
|
|
SkeletalControlAlpha = FMath::Clamp<float>(InSkeletalControlAlpha, 0.f, 1.f);
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
void SetKey()
|
|
{
|
|
bSetKey = true;
|
|
}
|
|
|
|
FDelegateHandle AddKeyCompleteDelegate(FSimpleMulticastDelegate::FDelegate InOnSetKeyCompleteDelegate)
|
|
{
|
|
return OnSetKeyCompleteDelegate.Add(InOnSetKeyCompleteDelegate);
|
|
}
|
|
|
|
void RemoveKeyCompleteDelegate(FDelegateHandle InDelegateHandle)
|
|
{
|
|
OnSetKeyCompleteDelegate.Remove(InDelegateHandle);
|
|
}
|
|
#endif
|
|
|
|
void RefreshCurveBoneControllers(UAnimationAsset* AssetToRefreshFrom);
|
|
|
|
TArray<FAnimNode_ModifyBone>& GetBoneControllers()
|
|
{
|
|
return BoneControllers;
|
|
}
|
|
|
|
TArray<FAnimNode_ModifyBone>& GetCurveBoneControllers()
|
|
{
|
|
return CurveBoneControllers;
|
|
}
|
|
|
|
virtual void AddImpulseAtLocation(FVector Impulse, FVector Location, FName BoneName = NAME_None) {}
|
|
|
|
/** Sets an external debug skeletal mesh component to use to debug */
|
|
void SetDebugSkeletalMeshComponent(USkeletalMeshComponent* InSkeletalMeshComponent);
|
|
|
|
/** Gets the external debug skeletal mesh component we are debugging */
|
|
USkeletalMeshComponent* GetDebugSkeletalMeshComponent() const;
|
|
|
|
private:
|
|
void UpdateCurveController();
|
|
|
|
void ApplyBoneControllers(TArray<FAnimNode_ModifyBone> &InBoneControllers, FComponentSpacePoseContext& ComponentSpacePoseContext);
|
|
|
|
void SetKeyImplementation(const FCompactPose& PreControllerInLocalSpace, const FCompactPose& PostControllerInLocalSpace);
|
|
|
|
void AddKeyToSequence(UAnimSequence* Sequence, float Time, const FName& BoneName, const FTransform& AdditiveTransform);
|
|
|
|
private:
|
|
/** Controllers for individual bones */
|
|
TArray<FAnimNode_ModifyBone> BoneControllers;
|
|
|
|
/** Curve modifiers */
|
|
TArray<FAnimNode_ModifyBone> CurveBoneControllers;
|
|
|
|
/** External curve for in-editor curve sources (such as audio) */
|
|
FAnimNode_CurveSource CurveSource;
|
|
|
|
/** Pose blend node for evaluating pose assets (for previewing curve sources) */
|
|
FAnimNode_PoseBlendNode PoseBlendNode;
|
|
|
|
/** Allows us to copy a pose from the mesh being debugged */
|
|
FAnimNode_CopyPoseFromMesh CopyPoseNode;
|
|
|
|
/**
|
|
* Delegate to call after Key is set
|
|
*/
|
|
FSimpleMulticastDelegate OnSetKeyCompleteDelegate;
|
|
|
|
/** Shared parameters for previewing blendspace or animsequence **/
|
|
float SkeletalControlAlpha;
|
|
|
|
/*
|
|
* Used to determine if controller has to be applied or not
|
|
* Used to disable controller during editing
|
|
*/
|
|
bool bEnableControllers;
|
|
|
|
/*
|
|
* When this flag is true, it sets key
|
|
*/
|
|
bool bSetKey;
|
|
};
|
|
|
|
/**
|
|
* This Instance only contains one AnimationAsset, and produce poses
|
|
* Used by Preview in AnimGraph, Playing single animation in Kismet2 and etc
|
|
*/
|
|
|
|
UCLASS(transient, NotBlueprintable, noteditinlinenew)
|
|
class ANIMGRAPH_API UAnimPreviewInstance : public UAnimSingleNodeInstance
|
|
{
|
|
GENERATED_UCLASS_BODY()
|
|
|
|
/** Shared parameters for previewing blendspace or animsequence **/
|
|
UPROPERTY(transient)
|
|
TEnumAsByte<enum EMontagePreviewType> MontagePreviewType;
|
|
|
|
UPROPERTY(transient)
|
|
int32 MontagePreviewStartSectionIdx;
|
|
|
|
//~ Begin UObject Interface
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
//~ End UObject Interface
|
|
|
|
//~ Begin UAnimInstance Interface
|
|
virtual void NativeInitializeAnimation() override;
|
|
virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
|
virtual bool CanRunParallelWork() const { return false; }
|
|
protected:
|
|
virtual void Montage_Advance(float DeltaTime) override;
|
|
//~ End UAnimInstance Interface
|
|
|
|
public:
|
|
/** Set SkeletalControl Alpha**/
|
|
void SetSkeletalControlAlpha(float SkeletalControlAlpha);
|
|
|
|
UAnimSequence* GetAnimSequence();
|
|
|
|
//~ Begin UAnimSingleNodeInstance Interface
|
|
virtual void RestartMontage(UAnimMontage* Montage, FName FromSection = FName()) override;
|
|
virtual void SetAnimationAsset(UAnimationAsset* NewAsset, bool bIsLooping = true, float InPlayRate = 1.f) override;
|
|
//~ End UAnimSingleNodeInstance Interface
|
|
|
|
/** Montage preview functions */
|
|
void MontagePreview_JumpToStart();
|
|
void MontagePreview_JumpToEnd();
|
|
void MontagePreview_JumpToPreviewStart();
|
|
void MontagePreview_Restart();
|
|
void MontagePreview_PreviewNormal(int32 FromSectionIdx = INDEX_NONE, bool bPlay = true);
|
|
void MontagePreview_SetLoopNormal(bool bIsLooping, int32 PreferSectionIdx = INDEX_NONE);
|
|
void MontagePreview_PreviewAllSections(bool bPlay = true);
|
|
void MontagePreview_SetLoopAllSections(bool bIsLooping);
|
|
void MontagePreview_SetLoopAllSetupSections(bool bIsLooping);
|
|
void MontagePreview_ResetSectionsOrder();
|
|
void MontagePreview_SetLooping(bool bIsLooping);
|
|
void MontagePreview_SetPlaying(bool bIsPlaying);
|
|
void MontagePreview_SetReverse(bool bInReverse);
|
|
void MontagePreview_StepForward();
|
|
void MontagePreview_StepBackward();
|
|
void MontagePreview_JumpToPosition(float NewPosition);
|
|
int32 MontagePreview_FindFirstSectionAsInMontage(int32 AnySectionIdx);
|
|
int32 MontagePreview_FindLastSection(int32 StartSectionIdx);
|
|
float MontagePreview_CalculateStepLength();
|
|
void MontagePreview_RemoveBlendOut();
|
|
bool IsPlayingMontage() { return GetActiveMontageInstance() != NULL; }
|
|
|
|
/**
|
|
* Finds an already modified bone
|
|
* @param InBoneName The name of the bone modification to find
|
|
* @return the bone modification or NULL if no current modification was found
|
|
*/
|
|
FAnimNode_ModifyBone* FindModifiedBone(const FName& InBoneName, bool bCurveController=false);
|
|
|
|
/**
|
|
* Modifies a single bone. Create a new FAnimNode_ModifyBone if one does not exist for the passed-in bone.
|
|
* @param InBoneName The name of the bone to modify
|
|
* @return the new or existing bone modification
|
|
*/
|
|
FAnimNode_ModifyBone& ModifyBone(const FName& InBoneName, bool bCurveController=false);
|
|
|
|
/**
|
|
* Removes an existing bone modification
|
|
* @param InBoneName The name of the existing modification to remove
|
|
*/
|
|
void RemoveBoneModification(const FName& InBoneName, bool bCurveController=false);
|
|
|
|
/**
|
|
* Reset all bone modified
|
|
*/
|
|
void ResetModifiedBone(bool bCurveController=false);
|
|
|
|
/**
|
|
* Returns all currently active bone controllers on this instance's proxy
|
|
*/
|
|
const TArray<FAnimNode_ModifyBone>& GetBoneControllers();
|
|
|
|
#if WITH_EDITOR
|
|
/**
|
|
* Convert current modified bone transforms (BoneControllers) to transform curves (CurveControllers)
|
|
* it does based on CurrentTime. This function does not set key directly here.
|
|
* It does wait until next update, and it gets the delta of transform before applying curves, and
|
|
* creates curves from it, so you'll need delegate if you'd like to do something after (set with SetKeyCompleteDelegate)
|
|
*/
|
|
void SetKey();
|
|
|
|
/**
|
|
* Add the delegate to be called when a key is set.
|
|
*
|
|
* @param Delegate To be called once set key is completed
|
|
*/
|
|
FDelegateHandle AddKeyCompleteDelegate(FSimpleMulticastDelegate::FDelegate InOnSetKeyCompleteDelegate);
|
|
|
|
/**
|
|
* Add the delegate to be called when a key is set.
|
|
*
|
|
* @param Delegate To be called once set key is completed
|
|
*/
|
|
void RemoveKeyCompleteDelegate(FDelegateHandle InDelegateHandle);
|
|
#endif
|
|
|
|
/**
|
|
* Refresh Curve Bone Controllers based on TransformCurves from Animation data
|
|
*/
|
|
void RefreshCurveBoneControllers();
|
|
|
|
/**
|
|
* Enable Controllers
|
|
* This is used by when editing, when controller has to be disabled
|
|
*/
|
|
void EnableControllers(bool bEnable);
|
|
|
|
/** Preview physics interaction */
|
|
void AddImpulseAtLocation(FVector Impulse, FVector Location, FName BoneName = NAME_None);
|
|
|
|
/** Sets an external debug skeletal mesh component to use to debug */
|
|
void SetDebugSkeletalMeshComponent(USkeletalMeshComponent* InSkeletalMeshComponent);
|
|
|
|
/** Gets the external debug skeletal mesh component we are debugging */
|
|
USkeletalMeshComponent* GetDebugSkeletalMeshComponent() const;
|
|
};
|
|
|
|
|
|
|