OLS/Source/OLSAnimation/Public/Nodes/AnimNode_OLSMask.h
2024-09-22 17:11:19 -04:00

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;
};