210 lines
6.3 KiB
C++
210 lines
6.3 KiB
C++
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "AnimNode_SlotCustom.h"
|
|
#include "Data/OLSMaskAnimationData.h"
|
|
#include "AnimNode_OLSMask.generated.h"
|
|
|
|
/**
|
|
*
|
|
*/
|
|
|
|
USTRUCT(BlueprintInternalUseOnly)
|
|
struct FOLSWeightCurves
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
FName OverrideCurve = NAME_None;
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
FName AdditiveCurve = NAME_None;
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
FName LocalSpaceBlendCurve = NAME_None;
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
FName MeshSpaceBlendCurve = NAME_None;
|
|
};
|
|
|
|
USTRUCT(BlueprintInternalUseOnly)
|
|
struct FOLSMaskSettings
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
FName BlendProfileName = NAME_None;
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
bool bUseMeshSpaceAdditive = false;
|
|
|
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category=Config)
|
|
bool bShouldAddSlot = false;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Config)
|
|
TEnumAsByte<ECurveBlendOption::Type> CurveBlendOption = ECurveBlendOption::Override;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Config)
|
|
FOLSWeightCurves WeightCurves;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Config)
|
|
FName SlotName = FAnimSlotGroup::DefaultSlotName;
|
|
|
|
// Transient properties should be declared at the end
|
|
UPROPERTY(Transient)
|
|
TObjectPtr<class UBlendProfile> BlendProfile = nullptr;
|
|
|
|
// Slot To Add If Needed
|
|
FAnimNode_SlotCustom Slot;
|
|
};
|
|
|
|
USTRUCT(BlueprintInternalUseOnly)
|
|
struct FOLSPerBoneWeights
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
|
|
// Constructor to reserve memory for the arrays.
|
|
// Assuming using Unreal's mannequin.
|
|
FOLSPerBoneWeights()
|
|
{
|
|
LocalSpaceDesiredBoneBlendWeights.Reserve(32);
|
|
MeshSpaceDesiredBoneBlendWeights.Reserve(32);
|
|
LocalSpaceCurrentBoneBlendWeights.Reserve(32);
|
|
MeshSpaceCurrentBoneBlendWeights.Reserve(32);
|
|
LocalCurvePoseSourceIndices.Reserve(32);
|
|
MeshCurvePoseSourceIndices.Reserve(32);
|
|
}
|
|
|
|
public:
|
|
|
|
UPROPERTY()
|
|
TArray<FPerBoneBlendWeight> LocalSpaceDesiredBoneBlendWeights;
|
|
|
|
UPROPERTY()
|
|
TArray<FPerBoneBlendWeight> MeshSpaceDesiredBoneBlendWeights;
|
|
|
|
UPROPERTY()
|
|
TArray<FPerBoneBlendWeight> LocalSpaceCurrentBoneBlendWeights;
|
|
|
|
UPROPERTY()
|
|
TArray<FPerBoneBlendWeight> MeshSpaceCurrentBoneBlendWeights;
|
|
|
|
// Using a more memory-efficient representation for the curves
|
|
TBaseBlendedCurve<FDefaultAllocator, UE::Anim::FCurveElementIndexed> LocalCurvePoseSourceIndices;
|
|
TBaseBlendedCurve<FDefaultAllocator, UE::Anim::FCurveElementIndexed> MeshCurvePoseSourceIndices;
|
|
};
|
|
|
|
USTRUCT(BlueprintInternalUseOnly)
|
|
struct FOLSPerBoneBlendWeights
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
|
|
UPROPERTY()
|
|
TArray<FPerBoneBlendWeight> PerBoneBlendWeights;
|
|
};
|
|
|
|
USTRUCT(BlueprintInternalUseOnly)
|
|
struct OLSANIMATION_API FAnimNode_OLSMask : public FAnimNode_Base
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
FAnimNode_OLSMask()
|
|
: bHasRelevantPoses(false)
|
|
, LODThreshold(INDEX_NONE)
|
|
, RequiredBonesSerialNumber(0)
|
|
{
|
|
}
|
|
|
|
// FAnimNode_Base interface
|
|
virtual void Initialize_AnyThread(const FAnimationInitializeContext& context) override;
|
|
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& context) override;
|
|
virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
|
virtual void Evaluate_AnyThread(FPoseContext& output) override;
|
|
virtual int32 GetLODThreshold() const override { return LODThreshold; }
|
|
|
|
// Invalidate the cached per-bone blend weights from the skeleton
|
|
void InvalidatePerBoneBlendWeights();
|
|
|
|
// Invalidates the cached bone data so it is recalculated the next time this node is updated
|
|
void InvalidateCachedBoneData();
|
|
|
|
// Rebuild cache per bone blend weights from the skeleton
|
|
void RebuildPerBoneBlendWeights(const USkeleton* skeleton);
|
|
|
|
// Check whether per-bone blend weights are valid according to the skeleton (GUID check)
|
|
bool ArePerBoneBlendWeightsValid(const USkeleton* skeleton) const;
|
|
|
|
// Update cached data if required
|
|
void UpdateCachedBoneData(const FBoneContainer& requiredBones, const USkeleton* skeleton);
|
|
|
|
void UpdateBodyPartCachedBoneData(const FBoneContainer& requiredBones, const USkeleton* skeleton, const int32 maskIndex);
|
|
|
|
void UpdateWeightsFromCurves(const USkeleton* skeleton, const FPoseContext& desiredCurvesPose, const int32 index);
|
|
|
|
static void MakeAdditivePose(FPoseContext& outAdditivePose,FPoseContext& outBasePose, const bool shouldUseMeshSpaceAdditive);
|
|
|
|
public:
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Links)
|
|
FPoseLink AnimationPose;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Links)
|
|
FPoseLink MaskPose;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Links)
|
|
FPoseLink BaseAdditivePose;
|
|
|
|
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite, Category=Config)
|
|
TArray<FOLSMaskSettings> BlendMasks;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Runtime, meta=(PinShownByDefault))
|
|
TArray<FOLSNodeMaskWeights> MaskBlendWeights;
|
|
|
|
uint8 bHasRelevantPoses : 1;
|
|
|
|
/*
|
|
* Max LOD that this node is allowed to run
|
|
* For example if you have LODThreadhold to be 2, it will run until LOD 2 (based on 0 index)
|
|
* when the component LOD becomes 3, it will stop update/evaluate
|
|
* currently transition would be issue and that has to be re-visited
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Performance, meta = (DisplayName = "LOD Threshold"))
|
|
int32 LODThreshold = 0;
|
|
|
|
// transient data to handle weight and target weight
|
|
// this array changes based on required bones
|
|
UPROPERTY()
|
|
TArray<FOLSPerBoneWeights> AllBoneBlendWeights;
|
|
|
|
protected:
|
|
|
|
// Per-bone weights for the skeleton. Serialized as these are only relative to the skeleton, but can potentially
|
|
// be regenerated at runtime if the GUIDs dont match.
|
|
UPROPERTY()
|
|
TArray<FOLSPerBoneBlendWeights> PerBoneBlendWeights;
|
|
|
|
// Guids for skeleton used to determine whether the PerBoneBlendWeights need rebuilding
|
|
UPROPERTY()
|
|
FGuid SkeletonGuid;
|
|
|
|
// Guid for virtual bones used to determine whether the PerBoneBlendWeights need rebuilding
|
|
UPROPERTY()
|
|
FGuid VirtualBoneGuid;
|
|
|
|
// Serial number of the required bones container
|
|
uint16 RequiredBonesSerialNumber : 1;
|
|
|
|
private:
|
|
|
|
friend class UAnimGraphNode_KLSMask;
|
|
};
|