// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "FbxAPI.h" #include "FbxHelper.h" #include "FbxInclude.h" /** Forward declarations */ struct FInterchangeCurve; struct FMeshDescription; class UInterchangeBaseNodeContainer; class UInterchangeMeshNode; class UInterchangeSceneNode; class UInterchangeSkeletalAnimationTrackNode; namespace UE::Interchange { struct FAnimationPayloadQuery; } namespace UE::Interchange::Private { struct FMorphTargetAnimationBuildingData; //Skeletal/Rigged Animation struct FNodeTransformFetchPayloadData { FbxNode* Node = nullptr; FbxAnimStack* CurrentAnimStack = nullptr; bool bIsRootJoint = false; }; //User defined animations: struct FAttributeFetchPayloadData { FbxNode* Node = nullptr; FbxAnimCurveNode* AnimCurves = nullptr; //If true the payload is TArray, if false the payload is TArray bool bAttributeTypeIsStepCurveAnimation = false; fbxsdk::EFbxType PropertyType = fbxsdk::EFbxType::eFbxUndefined; FbxProperty Property; }; //Rigid Animation struct FAttributeNodeTransformFetchPayloadData { double FrameRate = 30.0; FbxNode* Node = nullptr; FbxAnimCurveNode* TranlsationCurveNode = nullptr; FbxAnimCurveNode* RotationCurveNode = nullptr; FbxAnimCurveNode* ScaleCurveNode = nullptr; }; struct FMorphTargetFetchPayloadData { //We cannot just store the FbxAnimCurve // because! it is referenced from FbxMesh which gets replaced when we are triangulating it upon PayloadData acquisition // for that reason we need to re-acquire it all the way from the Scene, based on GeometryIndex, MorphTargetIndex, ChannelIndex and AnimLayer. // (This is happening because upon Triangulation we are passing bReplace = true, see @FMeshDescriptionImporter::FillMeshDescriptionFromFbxMesh) //FbxAnimCurve* MorphTargetAnimCurve = nullptr; FbxScene* SDKScene; int32 GeometryIndex; int32 MorphTargetIndex; int32 ChannelIndex; FbxAnimLayer* AnimLayer; //In between blend shape animation support //The count of the curve names should match the in between full weights TArray InbetweenCurveNames; TArray InbetweenFullWeights; }; class FAnimationPayloadContext : public FPayloadContextBase { public: virtual ~FAnimationPayloadContext() {} virtual FString GetPayloadType() const override { return TEXT("TransformAnimation-PayloadContext"); } virtual bool FetchPayloadToFile(FFbxParser& Parser, const FString& PayloadFilepath) override; virtual bool FetchAnimationBakeTransformPayloadForTime(FFbxParser& Parser, const FbxTime Currenttime, FTransform& Out) override; virtual FbxAnimStack* GetAnimStack() override; TOptional NodeTransformFetchPayloadData; TOptional AttributeFetchPayloadData; TOptional AttributeNodeTransformFetchPayloadData; TOptional MorphTargetFetchPayloadData; private: bool InternalFetchCurveNodePayloadToFile(FFbxParser& Parser, const FString& PayloadFilepath); bool InternalFetchMorphTargetCurvePayloadToFile(FFbxParser& Parser, const FString& PayloadFilepath); bool InternalFetchMorphTargetCurvePayload(FFbxParser& Parser, TArray& InterchangeCurves); }; class FFbxAnimation { public: /** This function add the payload key if the scene node transform is animated. */ static bool AddSkeletalTransformAnimation(UInterchangeBaseNodeContainer& NodeContainer , FbxScene* SDKScene , FFbxParser& Parser , FbxNode* Node , UInterchangeSceneNode* UnrealNode , TMap>& PayloadContexts , UInterchangeSkeletalAnimationTrackNode* SkeletalAnimationTrackNode , const int32& AnimationIndex , bool bIsRootJoint); /** This function add the payload key for an animated node user attribute. */ static void AddNodeAttributeCurvesAnimation(FFbxParser& Parser , FbxNode* Node , FbxProperty& Property , FbxAnimCurveNode* AnimCurveNode , UInterchangeSceneNode* SceneNode , TMap>& PayloadContexts , EFbxType PropertyType , TOptional& OutPayloadKey , TOptional& OutIsStepCurve); static void AddRigidTransformAnimation(FFbxParser& Parser , FbxNode* Node , FbxAnimCurveNode* TranslationCurveNode , FbxAnimCurveNode* RotationCurveNode , FbxAnimCurveNode* ScaleCurveNode , TMap>& PayloadContexts , TOptional& OutPayloadKey); /** This function add the payload key for an animated curve for morph target. */ static void AddMorphTargetCurvesAnimation(FbxScene* SDKScene , FFbxParser& Parser , UInterchangeSkeletalAnimationTrackNode* SkeletalAnimationTrackNode , TMap>& PayloadContexts , const FMorphTargetAnimationBuildingData& MorphTargetAnimationBuildingData); static bool IsFbxPropertyTypeSupported(EFbxType PropertyType); static bool IsFbxPropertyTypeDecimal(EFbxType PropertyType); //PayloadQueries arriving here should be of the same start/stop and frequency: static bool FetchAnimationBakeTransformPayload(FFbxParser& Parser, FbxScene* SDKScene, TMap>& PayloadContexts, const TArray& PayloadQueries, const FString& ResultFolder, FCriticalSection* ResultPayloadsCriticalSection, TAtomic& UniqueIdCounter, TMap& ResultPayloads, TArray& OutErrorMessages); }; }//ns UE::Interchange::Private