diff --git a/Source/OLSAnimation/Private/Data/OLSMaskAnimationData.cpp b/Source/OLSAnimation/Private/Data/OLSMaskAnimationData.cpp deleted file mode 100644 index 3151ffc..0000000 --- a/Source/OLSAnimation/Private/Data/OLSMaskAnimationData.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. - - -#include "Data/OLSMaskAnimationData.h" - -void FOLSMaskAnimation::CacheAdditiveCurves() -{ -#if WITH_EDITOR - if (!Animation) - { - CurvesToModify.Reset(); - return; - } - - MaskPoseTime = FMath::Clamp(MaskPoseTime, 0.f, Animation->GetPlayLength()); - - //Set values for Arms Spaces To 0 Before Filling them from the Weights. - MaskingWeights.RightArmWeights.ArmLocalSpaceBlend = 0.f; - MaskingWeights.RightArmWeights.ArmMeshSpaceBlend = 0.f; - MaskingWeights.LeftArmWeights.ArmLocalSpaceBlend = 0.f; - MaskingWeights.LeftArmWeights.ArmMeshSpaceBlend = 0.f; - - //Fill arm spaces values with weights - if (MaskingWeights.RightArmWeights.ArmAdditiveMode == EOLSAdditiveMode::ELocalSpace) - { - MaskingWeights.RightArmWeights.ArmLocalSpaceBlend = 1.f; - } - else - { - MaskingWeights.RightArmWeights.ArmMeshSpaceBlend = 1.f; - } - - if (MaskingWeights.LeftArmWeights.ArmAdditiveMode == EOLSAdditiveMode::ELocalSpace) - { - MaskingWeights.LeftArmWeights.ArmLocalSpaceBlend = 1.f; - } - else - { - MaskingWeights.LeftArmWeights.ArmMeshSpaceBlend = 1.f; - } - - CurvesToModify.Reset(); - - // Legs - CurvesToModify.Add(MaskLegsMeshSpaceCurveName, 1); - CurvesToModify.Add(MaskLegsLocalSpaceCurveName, 0); - CurvesToModify.Add(MaskLegsCurveName, MaskingWeights.LegsWeights.MaskWeight); - CurvesToModify.Add(MaskLegsAddCurveName, MaskingWeights.LegsWeights.MaskAdditive); - Weights.LegsWeights.OverrideAlpha = MaskingWeights.LegsWeights.MaskWeight; - Weights.LegsWeights.AdditiveAlpha = MaskingWeights.LegsWeights.MaskAdditive; - - // Pelvis - CurvesToModify.Add(MaskPelvisMeshSpaceCurveName, 1); - CurvesToModify.Add(MaskPelvisLocalSpaceCurveName, 0); - CurvesToModify.Add(MaskPelvisCurveName, MaskingWeights.PelvisWeights.MaskWeight); - CurvesToModify.Add(MaskPelvisAddCurveName, MaskingWeights.PelvisWeights.MaskAdditive); - Weights.PelvisWeights.OverrideAlpha = MaskingWeights.PelvisWeights.MaskWeight; - Weights.PelvisWeights.AdditiveAlpha = MaskingWeights.PelvisWeights.MaskAdditive; - - // Spine - CurvesToModify.Add(MaskSpineMeshSpaceCurveName, 1); - CurvesToModify.Add(MaskSpineLocalSpaceCurveName, 0); - CurvesToModify.Add(MaskSpineCurveName, MaskingWeights.SpineWeights.MaskWeight); - CurvesToModify.Add(MaskSpineAddCurveName, MaskingWeights.SpineWeights.MaskAdditive); - Weights.SpineWeights.OverrideAlpha = MaskingWeights.SpineWeights.MaskWeight; - Weights.SpineWeights.AdditiveAlpha = MaskingWeights.SpineWeights.MaskAdditive; - - // Head - CurvesToModify.Add(MaskHeadMeshSpaceCurveName, 1); - CurvesToModify.Add(MaskHeadLocalSpaceCurveName, 0); - CurvesToModify.Add(MaskHeadCurveName, MaskingWeights.HeadWeights.MaskWeight); - CurvesToModify.Add(MaskHeadAddCurveName, MaskingWeights.HeadWeights.MaskAdditive); - Weights.HeadWeights.OverrideAlpha = MaskingWeights.HeadWeights.MaskWeight; - Weights.HeadWeights.AdditiveAlpha = MaskingWeights.HeadWeights.MaskAdditive; - - // Right Arm - CurvesToModify.Add(MaskRightArmCurveName, MaskingWeights.RightArmWeights.MaskWeights.MaskWeight); - CurvesToModify.Add(RightArmMeshSpaceCurveName, MaskingWeights.RightArmWeights.ArmMeshSpaceBlend); - CurvesToModify.Add(RightArmLocalSpaceCurveName, MaskingWeights.RightArmWeights.ArmLocalSpaceBlend); - CurvesToModify.Add(MaskRightArmAddCurveName, MaskingWeights.RightArmWeights.MaskWeights.MaskAdditive); - Weights.RightArmWeights.OverrideAlpha = MaskingWeights.RightArmWeights.MaskWeights.MaskWeight; - Weights.RightArmWeights.AdditiveAlpha = MaskingWeights.RightArmWeights.MaskWeights.MaskAdditive; - Weights.RightArmWeights.LocalSpaceBlendAlpha = MaskingWeights.RightArmWeights.ArmLocalSpaceBlend; - Weights.RightArmWeights.MeshSpaceBlendAlpha = MaskingWeights.RightArmWeights.ArmMeshSpaceBlend; - - // Left Arm - CurvesToModify.Add(LeftArmMeshSpaceCurveName, MaskingWeights.LeftArmWeights.ArmMeshSpaceBlend); - CurvesToModify.Add(LeftArmLocalSpaceCurveName, MaskingWeights.LeftArmWeights.ArmLocalSpaceBlend); - CurvesToModify.Add(MaskLeftArmCurveName, MaskingWeights.LeftArmWeights.MaskWeights.MaskWeight); - CurvesToModify.Add(MaskLeftArmAddCurveName, MaskingWeights.LeftArmWeights.MaskWeights.MaskAdditive); - Weights.LeftArmWeights.OverrideAlpha = MaskingWeights.LeftArmWeights.MaskWeights.MaskWeight; - Weights.LeftArmWeights.AdditiveAlpha = MaskingWeights.LeftArmWeights.MaskWeights.MaskAdditive; - Weights.LeftArmWeights.LocalSpaceBlendAlpha = MaskingWeights.LeftArmWeights.ArmLocalSpaceBlend; - Weights.LeftArmWeights.MeshSpaceBlendAlpha = MaskingWeights.LeftArmWeights.ArmMeshSpaceBlend; - - // Right Hand - CurvesToModify.Add(RightHandMeshSpaceCurveName, 0); - CurvesToModify.Add(RightHandLocalSpaceCurveName, 1); - CurvesToModify.Add(RightHandCurveName, MaskingWeights.RightHandWeights.MaskWeight); - CurvesToModify.Add(MaskRightHandAddCurveName, MaskingWeights.RightHandWeights.MaskAdditive); - Weights.RightHandWeights.OverrideAlpha = MaskingWeights.RightHandWeights.MaskWeight; - Weights.RightHandWeights.AdditiveAlpha = MaskingWeights.RightHandWeights.MaskAdditive; - Weights.RightHandWeights.LocalSpaceBlendAlpha = 1.f; - Weights.RightHandWeights.MeshSpaceBlendAlpha = 0.f; - - // Left Hand - CurvesToModify.Add(LeftHandMeshSpaceCurveName, 0); - CurvesToModify.Add(LeftHandLocalSpaceCurveName, 1); - CurvesToModify.Add(LeftHandCurveName, MaskingWeights.LeftHandWeights.MaskWeight); - CurvesToModify.Add(MaskLeftHandAddCurveName, MaskingWeights.LeftHandWeights.MaskAdditive); - Weights.LeftHandWeights.OverrideAlpha = MaskingWeights.LeftHandWeights.MaskWeight; - Weights.LeftHandWeights.AdditiveAlpha = MaskingWeights.LeftHandWeights.MaskAdditive; - Weights.LeftHandWeights.LocalSpaceBlendAlpha = 1.f; - Weights.LeftHandWeights.MeshSpaceBlendAlpha = 0.f; - -#endif -} - -void FOLSGaitMasks::CacheAdditiveCurves() -{ -#if WITH_EDITOR - ForwardMask.CacheAdditiveCurves(); - RightMask.CacheAdditiveCurves(); - LeftMask.CacheAdditiveCurves(); - BackwardMask.CacheAdditiveCurves(); -#endif -} - -void FOLSStanceMaskSets::CacheAdditiveCurves() -{ -#if WITH_EDITOR - for (TPair& pair : GaitMasks) - { - pair.Value.CacheAdditiveCurves(); - } - - IdleMask.CacheAdditiveCurves(); - AimMask.CacheAdditiveCurves(); -#endif -} - -const FOLSGaitMasks* FOLSStanceMaskSets::SelectGaitMasksByGait(const FGameplayTag& gait) -{ - return GaitMasks.Find(gait); -} - -const FOLSMaskAnimation& FOLSStanceMaskSets::GetIdleMask() const -{ - return IdleMask; -} - -const FOLSMaskAnimation& FOLSStanceMaskSets::GetAimMask() const -{ - return AimMask; -} - -void FOLSStanceMaskSets::GetAimBlendInOut(float& outBlendIn, float& outBlendOut) const -{ - outBlendIn = AimBlendInTime; - outBlendOut = AimBlendOutTime; -} \ No newline at end of file diff --git a/Source/OLSAnimation/Private/Nodes/AnimNode_OLSMask.cpp b/Source/OLSAnimation/Private/Nodes/AnimNode_OLSMask.cpp deleted file mode 100644 index 66875ff..0000000 --- a/Source/OLSAnimation/Private/Nodes/AnimNode_OLSMask.cpp +++ /dev/null @@ -1,495 +0,0 @@ -// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. - - -#include "Nodes/AnimNode_OLSMask.h" - -#include "Animation/AnimInstanceProxy.h" - -void FAnimNode_OLSMask::Initialize_AnyThread(const FAnimationInitializeContext& context) -{ - // Don't call SUPER since it's empty. - - DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Initialize_AnyThread) - FAnimNode_Base::Initialize_AnyThread(context); - - AnimationPose.Initialize(context); - MaskPose.Initialize(context); - BaseAdditivePose.Initialize(context); - - - for (int32 index = 0; index < BlendMasks.Num(); ++index) - { - if (BlendMasks[index].bShouldAddSlot) - { - BlendMasks[index].Slot.SlotName = BlendMasks[index].SlotName; - BlendMasks[index].Slot.Source = MaskPose; - BlendMasks[index].Slot.Initialize_AnyThread(context); - } - } - if (!context.AnimInstanceProxy->GetSkeleton()) - { - return; - } - - // Invalidate the cached per-bone blend weights from the skeleton - InvalidatePerBoneBlendWeights(); -} - -void FAnimNode_OLSMask::CacheBones_AnyThread(const FAnimationCacheBonesContext& context) -{ - // Don't call SUPER since it's empty. - - DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread) - AnimationPose.CacheBones(context); - BaseAdditivePose.CacheBones(context); - MaskPose.CacheBones(context); - const int32 numBlendMasks = BlendMasks.Num(); - for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) - { - const FOLSMaskSettings currentMask = BlendMasks[maskIndex]; - const FName blendProfileName = BlendMasks[maskIndex].BlendProfileName; - if (const TObjectPtr blendProfile = context.AnimInstanceProxy->GetSkeleton()->GetBlendProfile( - blendProfileName)) - { - BlendMasks[maskIndex].BlendProfile = blendProfile; - } - if (BlendMasks[maskIndex].bShouldAddSlot) - { - BlendMasks[maskIndex].Slot.CacheBones_AnyThread(context); - } - } - - UpdateCachedBoneData(context.AnimInstanceProxy->GetRequiredBones(), context.AnimInstanceProxy->GetSkeleton()); -} - -void FAnimNode_OLSMask::Update_AnyThread(const FAnimationUpdateContext& Context) -{ - // Don't call SUPER since it's empty. - - DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Update_AnyThread) - bHasRelevantPoses = false; - if (BlendMasks.Num() > 0) - { - if (IsLODEnabled(Context.AnimInstanceProxy)) - { - GetEvaluateGraphExposedInputs().Execute(Context); - - if (!bHasRelevantPoses) - { - MaskPose.Update(Context); - BaseAdditivePose.Update(Context); - AnimationPose.Update(Context); - for (int32 Index = 0; Index < BlendMasks.Num(); ++Index) - { - if (BlendMasks[Index].bShouldAddSlot) - { - BlendMasks[Index].Slot.Update_AnyThread(Context); - } - } - UpdateCachedBoneData(Context.AnimInstanceProxy->GetRequiredBones(), - Context.AnimInstanceProxy->GetSkeleton()); - - bHasRelevantPoses = true; - } - return; - } - - // Clear BlendWeights if disabled by LODThreshold. - for (int32 ChildIndex = 0; ChildIndex < MaskBlendWeights.Num(); ++ChildIndex) - { - MaskBlendWeights[ChildIndex].LocalSpaceBlendAlpha = 0.0f; - MaskBlendWeights[ChildIndex].MeshSpaceBlendAlpha = 0.0f; - } - - return; - } - - AnimationPose.Update(Context); -} - -void FAnimNode_OLSMask::Evaluate_AnyThread(FPoseContext& output) -{ - // Don't call SUPER since it's empty. - - if (BlendMasks.Num() > 0) - { - AnimationPose.Evaluate(output); - FPoseContext animationPoseContext(output); - animationPoseContext = output; - - FPoseContext updatedAnimationPoseContext(output); - updatedAnimationPoseContext = animationPoseContext; - - FPoseContext maskPoseContext(output); - MaskPose.Evaluate(maskPoseContext); - - FPoseContext baseAddPoseContext(output); - BaseAdditivePose.Evaluate(baseAddPoseContext); - - FPoseContext baseMSAddPoseContext(output); - baseMSAddPoseContext = baseAddPoseContext; - - FPoseContext animationLocalSpaceAdditive(output); - animationLocalSpaceAdditive = animationPoseContext; - - FPoseContext animationMeshSpaceAdditive(output); - animationMeshSpaceAdditive = animationPoseContext; - - MakeAdditivePose(animationLocalSpaceAdditive, baseAddPoseContext, false); - MakeAdditivePose(animationMeshSpaceAdditive, baseMSAddPoseContext, true); - - for (int32 maskIndex = 0; maskIndex < BlendMasks.Num(); ++maskIndex) - { - //Apply Blending For Each Mask - TArray lsTargetBlendPoses; - lsTargetBlendPoses.SetNum(1); - - TArray msTargetBlendPoses; - msTargetBlendPoses.SetNum(1); - - TArray lsTargetBlendCurves; - lsTargetBlendCurves.SetNum(1); - - TArray msTargetBlendCurves; - msTargetBlendCurves.SetNum(1); - - TArray lsTargetBlendAttributes; - lsTargetBlendAttributes.SetNum(1); - - TArray msTargetBlendAttributes; - msTargetBlendAttributes.SetNum(1); - - FPoseContext outMaskPoseContext(output); - (BlendMasks[maskIndex].bShouldAddSlot) - ? BlendMasks[maskIndex].Slot.Evaluate_AnyThread(outMaskPoseContext) - : BlendMasks[maskIndex].Slot.Evaluate_AnyThread(outMaskPoseContext); - - UpdateWeightsFromCurves(output.AnimInstanceProxy->GetSkeleton(), outMaskPoseContext, maskIndex); - - FAnimationPoseData inOutAnimationPoseData(outMaskPoseContext); - const FAnimationPoseData additiveAnimationPoseData( - BlendMasks[maskIndex].bUseMeshSpaceAdditive ? animationMeshSpaceAdditive : animationLocalSpaceAdditive); - if (FAnimWeight::IsRelevant(MaskBlendWeights[maskIndex].AdditiveAlpha)) - { - FAnimationRuntime::AccumulateAdditivePose(inOutAnimationPoseData, additiveAnimationPoseData, - MaskBlendWeights[maskIndex].AdditiveAlpha, - BlendMasks[maskIndex].bUseMeshSpaceAdditive - ? AAT_RotationOffsetMeshSpace - : AAT_LocalSpaceBase); - outMaskPoseContext.Pose.NormalizeRotations(); - } - - - FPoseContext currentPoseContext(animationPoseContext); - FAnimationPoseData blendedAnimationPoseData(currentPoseContext); - const FAnimationPoseData animationPoseOneData(animationPoseContext); - const FAnimationPoseData animationPoseTwoData(outMaskPoseContext); - - - TArray lsDesiredBlendWeight; - lsDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha); - TArray msDesiredBlendWeight; - msDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].MeshSpaceBlendAlpha); - FAnimationRuntime::UpdateDesiredBoneWeight(AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights, - AllBoneBlendWeights[maskIndex].LocalSpaceCurrentBoneBlendWeights, - lsDesiredBlendWeight); - FAnimationRuntime::UpdateDesiredBoneWeight(AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights, - AllBoneBlendWeights[maskIndex].MeshSpaceCurrentBoneBlendWeights, - msDesiredBlendWeight); - - FAnimationRuntime::BlendTwoPosesTogether(animationPoseOneData, animationPoseTwoData, - (1.0f - MaskBlendWeights[maskIndex].OverrideAlpha), - blendedAnimationPoseData); - - FPoseContext msCurrentPoseContext(animationPoseContext); - msCurrentPoseContext = currentPoseContext; - if (FAnimWeight::IsRelevant(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha)) - { - lsTargetBlendPoses[0].MoveBonesFrom(currentPoseContext.Pose); - lsTargetBlendCurves[0].MoveFrom(currentPoseContext.Curve); - lsTargetBlendAttributes[0].MoveFrom(currentPoseContext.CustomAttributes); - } - else - { - lsTargetBlendPoses[0].ResetToRefPose(animationPoseContext.Pose.GetBoneContainer()); - lsTargetBlendCurves[0].InitFrom(output.Curve); - } - - if (FAnimWeight::IsRelevant(MaskBlendWeights[maskIndex].MeshSpaceBlendAlpha)) - { - msTargetBlendPoses[0].MoveBonesFrom(msCurrentPoseContext.Pose); - msTargetBlendCurves[0].MoveFrom(msCurrentPoseContext.Curve); - msTargetBlendAttributes[0].MoveFrom(msCurrentPoseContext.CustomAttributes); - } - else - { - msTargetBlendPoses[0].ResetToRefPose(animationPoseContext.Pose.GetBoneContainer()); - msTargetBlendCurves[0].InitFrom(output.Curve); - } - - // Filter to make sure it only includes curves that are linked to the correct bone filter - UE::Anim::FNamedValueArrayUtils::RemoveByPredicate(animationPoseContext.Curve, - AllBoneBlendWeights[maskIndex]. - LocalCurvePoseSourceIndices, - [](const UE::Anim::FCurveElement& inOutBasePoseElement, - const UE::Anim::FCurveElementIndexed& - inSourceIndexElement) - { - // if source index is set, remove base pose curve value - return (inSourceIndexElement.Index != INDEX_NONE); - }); - - // Filter to make sure it only includes curves that are linked to the correct bone filter - UE::Anim::FNamedValueArrayUtils::RemoveByPredicate(animationPoseContext.Curve, - AllBoneBlendWeights[maskIndex]. - MeshCurvePoseSourceIndices, - [](const UE::Anim::FCurveElement& inOutBasePoseElement, - const UE::Anim::FCurveElementIndexed& - inSourceIndexElement) - { - // if source index is set, remove base pose curve value - return (inSourceIndexElement.Index != INDEX_NONE); - }); - - - FAnimationRuntime::EBlendPosesPerBoneFilterFlags msBlendFlags = - FAnimationRuntime::EBlendPosesPerBoneFilterFlags::None; - msBlendFlags |= FAnimationRuntime::EBlendPosesPerBoneFilterFlags::MeshSpaceRotation; - - FAnimationRuntime::EBlendPosesPerBoneFilterFlags lsBlendFlags = - FAnimationRuntime::EBlendPosesPerBoneFilterFlags::None; - if (FAnimWeight::IsRelevant(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha)) - { - FAnimationPoseData animationPoseData(output); - FAnimationRuntime::BlendPosesPerBoneFilter(updatedAnimationPoseContext.Pose, lsTargetBlendPoses, - updatedAnimationPoseContext.Curve, lsTargetBlendCurves, - updatedAnimationPoseContext.CustomAttributes, - lsTargetBlendAttributes, animationPoseData, - AllBoneBlendWeights[maskIndex]. - LocalSpaceCurrentBoneBlendWeights, lsBlendFlags, - BlendMasks[maskIndex].CurveBlendOption); - updatedAnimationPoseContext = output; - updatedAnimationPoseContext.Pose.NormalizeRotations(); - } - - if (FAnimWeight::IsRelevant(MaskBlendWeights[maskIndex].MeshSpaceBlendAlpha)) - { - FAnimationPoseData MSAnimationPoseData(output); - FAnimationRuntime::BlendPosesPerBoneFilter(updatedAnimationPoseContext.Pose, msTargetBlendPoses, - updatedAnimationPoseContext.Curve, msTargetBlendCurves, - updatedAnimationPoseContext.CustomAttributes, - msTargetBlendAttributes, MSAnimationPoseData, - AllBoneBlendWeights[maskIndex]. - MeshSpaceCurrentBoneBlendWeights, msBlendFlags, - BlendMasks[maskIndex].CurveBlendOption); - updatedAnimationPoseContext = output; - updatedAnimationPoseContext.Pose.NormalizeRotations(); - } - } - - return; - } - - AnimationPose.Evaluate(output); -} - -void FAnimNode_OLSMask::InvalidatePerBoneBlendWeights() -{ - RequiredBonesSerialNumber = 0; - SkeletonGuid = FGuid(); - VirtualBoneGuid = FGuid(); -} - -void FAnimNode_OLSMask::InvalidateCachedBoneData() -{ - RequiredBonesSerialNumber = 0; -} - -void FAnimNode_OLSMask::RebuildPerBoneBlendWeights(const USkeleton* skeleton) -{ - if (skeleton) - { - if (BlendMasks.Num() > 0) - { - PerBoneBlendWeights.SetNum(BlendMasks.Num()); - TArray currentBlendProfile; - for (int32 Index = 0; Index < BlendMasks.Num(); ++Index) - { - if (BlendMasks[Index].BlendProfile && BlendMasks[Index].BlendProfile->IsBlendMask()) - { - currentBlendProfile.Reset(); - currentBlendProfile.Add(BlendMasks[Index].BlendProfile); - FAnimationRuntime::CreateMaskWeights(PerBoneBlendWeights[Index].PerBoneBlendWeights, - currentBlendProfile, skeleton); - } - else - { - const FReferenceSkeleton& refSkeleton = skeleton->GetReferenceSkeleton(); - const int32 numBones = refSkeleton.GetNum(); - PerBoneBlendWeights[Index].PerBoneBlendWeights.Reset(numBones); - // We only store non-zero weights in blend masks. Initialize all to zero. - PerBoneBlendWeights[Index].PerBoneBlendWeights.AddZeroed(numBones); - } - } - } - - SkeletonGuid = skeleton->GetGuid(); - VirtualBoneGuid = skeleton->GetVirtualBoneGuid(); - } -} - -bool FAnimNode_OLSMask::ArePerBoneBlendWeightsValid(const USkeleton* skeleton) const -{ - return (skeleton && skeleton->GetGuid() == SkeletonGuid && skeleton->GetVirtualBoneGuid() == VirtualBoneGuid); -} - -void FAnimNode_OLSMask::UpdateCachedBoneData(const FBoneContainer& requiredBones, const USkeleton* skeleton) -{ - if (requiredBones.GetSerialNumber() == RequiredBonesSerialNumber) - { - return; - } - - if (requiredBones.GetBoneIndicesArray().Num() > 0) - { - if (!ArePerBoneBlendWeightsValid(skeleton)) - { - RebuildPerBoneBlendWeights(skeleton); - } - - for (int32 Index = 0; Index < BlendMasks.Num(); ++Index) - { - UpdateBodyPartCachedBoneData(requiredBones, skeleton, Index); - } - - RequiredBonesSerialNumber = requiredBones.GetSerialNumber(); - } -} - -void FAnimNode_OLSMask::UpdateBodyPartCachedBoneData(const FBoneContainer& requiredBones, const USkeleton* skeleton, - const int32 maskIndex) -{ - const TArray& requiredBoneIndices = requiredBones.GetBoneIndicesArray(); - const int32 numRequiredBones = requiredBoneIndices.Num(); - AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights.SetNumZeroed(numRequiredBones); - AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights.SetNumZeroed(numRequiredBones); - for (int32 requiredBoneIndex = 0; requiredBoneIndex < numRequiredBones; requiredBoneIndex++) - { - const int32 skeletonBoneIndex = requiredBones.GetSkeletonIndex(FCompactPoseBoneIndex(requiredBoneIndex)); - if (ensure(skeletonBoneIndex != INDEX_NONE)) - { - AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights[requiredBoneIndex] = PerBoneBlendWeights[ - maskIndex].PerBoneBlendWeights[skeletonBoneIndex]; - AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights[requiredBoneIndex] = PerBoneBlendWeights[ - maskIndex].PerBoneBlendWeights[skeletonBoneIndex]; - } - } - AllBoneBlendWeights[maskIndex].LocalSpaceCurrentBoneBlendWeights.Reset( - AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights.Num()); - AllBoneBlendWeights[maskIndex].MeshSpaceCurrentBoneBlendWeights.Reset( - AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights.Num()); - AllBoneBlendWeights[maskIndex].LocalSpaceCurrentBoneBlendWeights.AddZeroed( - AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights.Num()); - AllBoneBlendWeights[maskIndex].MeshSpaceCurrentBoneBlendWeights.AddZeroed( - AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights.Num()); - TArray lsDesiredBlendWeight; - lsDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha); - TArray msDesiredBlendWeight; - msDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].MeshSpaceBlendAlpha); - FAnimationRuntime::UpdateDesiredBoneWeight(AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights, - AllBoneBlendWeights[maskIndex].LocalSpaceCurrentBoneBlendWeights, - lsDesiredBlendWeight); - FAnimationRuntime::UpdateDesiredBoneWeight(AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights, - AllBoneBlendWeights[maskIndex].MeshSpaceCurrentBoneBlendWeights, - msDesiredBlendWeight); - - // Build curve source indices - AllBoneBlendWeights[maskIndex].LocalCurvePoseSourceIndices.Empty(); - AllBoneBlendWeights[maskIndex].LocalCurvePoseSourceIndices.Reserve(skeleton->GetNumCurveMetaData()); - skeleton->ForEachCurveMetaData( - [this, &requiredBones, maskIndex](const FName& curveName, const FCurveMetaData& metaData) - { - for (const FBoneReference& linkedBone : metaData.LinkedBones) - { - FCompactPoseBoneIndex compactPoseIndex = linkedBone.GetCompactPoseIndex(requiredBones); - if (compactPoseIndex != INDEX_NONE) - { - if (AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights[compactPoseIndex.GetInt()].BlendWeight > 0.f) - { - AllBoneBlendWeights[maskIndex].LocalCurvePoseSourceIndices.Add( - curveName, - AllBoneBlendWeights[maskIndex].LocalSpaceDesiredBoneBlendWeights[compactPoseIndex.GetInt()]. - SourceIndex); - break; - } - } - } - }); - - // Build curve source indices - AllBoneBlendWeights[maskIndex].MeshCurvePoseSourceIndices.Empty(); - AllBoneBlendWeights[maskIndex].MeshCurvePoseSourceIndices.Reserve(skeleton->GetNumCurveMetaData()); - skeleton->ForEachCurveMetaData( - [this, &requiredBones, maskIndex](const FName& curveName, const FCurveMetaData& metaData) - { - for (const FBoneReference& linkedBone : metaData.LinkedBones) - { - FCompactPoseBoneIndex compactPoseIndex = linkedBone.GetCompactPoseIndex(requiredBones); - if (compactPoseIndex != INDEX_NONE) - { - if (AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights[compactPoseIndex.GetInt()]. - BlendWeight > 0.f) - { - AllBoneBlendWeights[maskIndex].MeshCurvePoseSourceIndices.Add( - curveName, - AllBoneBlendWeights[maskIndex].MeshSpaceDesiredBoneBlendWeights[compactPoseIndex.GetInt()]. - SourceIndex); - break; - } - } - } - }); -} - -void FAnimNode_OLSMask::UpdateWeightsFromCurves(const USkeleton* skeleton, const FPoseContext& desiredCurvesPose, - const int32 index) -{ - if (BlendMasks[index].WeightCurves.OverrideCurve != NAME_None) - { - MaskBlendWeights[index].OverrideAlpha = desiredCurvesPose.Curve.Get( - BlendMasks[index].WeightCurves.OverrideCurve); - } - - if (BlendMasks[index].WeightCurves.AdditiveCurve != NAME_None) - { - MaskBlendWeights[index].AdditiveAlpha = desiredCurvesPose.Curve.Get( - BlendMasks[index].WeightCurves.AdditiveCurve); - } - - if (BlendMasks[index].WeightCurves.LocalSpaceBlendCurve != NAME_None) - { - MaskBlendWeights[index].LocalSpaceBlendAlpha = desiredCurvesPose.Curve.Get( - BlendMasks[index].WeightCurves.LocalSpaceBlendCurve); - } - - if (BlendMasks[index].WeightCurves.MeshSpaceBlendCurve != NAME_None) - { - MaskBlendWeights[index].MeshSpaceBlendAlpha = desiredCurvesPose.Curve.Get( - BlendMasks[index].WeightCurves.MeshSpaceBlendCurve); - } -} - -void FAnimNode_OLSMask::MakeAdditivePose(FPoseContext& outAdditivePose, FPoseContext& outBasePose, - const bool shouldUseMeshSpaceAdditive) -{ - if (shouldUseMeshSpaceAdditive) - { - FAnimationRuntime::ConvertPoseToMeshRotation(outAdditivePose.Pose); - FAnimationRuntime::ConvertPoseToMeshRotation(outBasePose.Pose); - } - - FAnimationRuntime::ConvertPoseToAdditive(outAdditivePose.Pose, outBasePose.Pose); - outAdditivePose.Curve.ConvertToAdditive(outBasePose.Curve); - - UE::Anim::Attributes::ConvertToAdditive(outBasePose.CustomAttributes, outAdditivePose.CustomAttributes); -} diff --git a/Source/OLSAnimation/Private/Nodes/AnimNode_SlotCustom.cpp b/Source/OLSAnimation/Private/Nodes/AnimNode_SlotCustom.cpp deleted file mode 100644 index a0c2cbc..0000000 --- a/Source/OLSAnimation/Private/Nodes/AnimNode_SlotCustom.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. - - -#include "Nodes/AnimNode_SlotCustom.h" - -#include "Animation/AnimInstanceProxy.h" -#include "Animation/AnimNode_Inertialization.h" - -void FAnimNode_SlotCustom::Update_AnyThread(const FAnimationUpdateContext& context) -{ - DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Update_AnyThread) - // Update weights. - context.AnimInstanceProxy->GetSlotWeight(SlotName, WeightData.SlotNodeWeight, WeightData.SourceWeight, WeightData.TotalNodeWeight); - - // Update cache in AnimInstance. - context.AnimInstanceProxy->UpdateSlotNodeWeight(SlotName, WeightData.SlotNodeWeight, context.GetFinalBlendWeight()); - - UE::Anim::FSlotInertializationRequest inertializationRequest; - if (context.AnimInstanceProxy->GetSlotInertializationRequest(SlotName, inertializationRequest)) - { - UE::Anim::IInertializationRequester* inertializationRequestr = context.GetMessage(); - if (inertializationRequestr) - { - inertializationRequestr->RequestInertialization(inertializationRequest.Get<0>(), inertializationRequest.Get<1>()); - } - else - { - FAnimNode_Inertialization::LogRequestError(context, Source); - } - } - - const bool shouldUpdateSource = (bAlwaysUpdateSourcePose || FAnimWeight::IsRelevant(WeightData.SourceWeight)); - if (shouldUpdateSource) - { - const float SourceWeight = FMath::Max(FAnimWeight::GetSmallestRelevantWeight(), WeightData.SourceWeight); - Source.Update(context.FractionalWeight(SourceWeight)); - } -#if ANIM_TRACE_ENABLED - TRACE_ANIM_NODE_VALUE(context, TEXT("Name"), SlotName); - TRACE_ANIM_NODE_VALUE(context, TEXT("Slot Weight"), WeightData.SlotNodeWeight); - TRACE_ANIM_NODE_VALUE(context, TEXT("Pose Source"), (WeightData.SourceWeight <= ZERO_ANIMWEIGHT_THRESH)); - - context.AnimInstanceProxy->TraceMontageEvaluationData(context, SlotName); -#endif -} diff --git a/Source/OLSAnimation/Public/Data/OLSMaskAnimationData.h b/Source/OLSAnimation/Public/Data/OLSMaskAnimationData.h deleted file mode 100644 index f1104c5..0000000 --- a/Source/OLSAnimation/Public/Data/OLSMaskAnimationData.h +++ /dev/null @@ -1,274 +0,0 @@ -// © 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 "GameplayTagContainer.h" -#include "UObject/Object.h" -#include "OLSMaskAnimationData.generated.h" - -//Enums -UENUM(BlueprintType) -enum class EOLSAdditiveMode : uint8 -{ - EMeshSpace UMETA(DisplayName = "MeshSpace"), - ELocalSpace UMETA(DisplayName = "LocalSpace"), -}; - -//Structs -USTRUCT(BlueprintType) -struct FOLSNodeMaskWeights -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config,meta=(ClampMin = "0.0" , ClampMax = "1.0") ) - float OverrideAlpha = 0.0f; - - UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0")) - float AdditiveAlpha = 0.0f; - - UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0")) - float MeshSpaceBlendAlpha = 1.0f; - - UPROPERTY(BlueprintReadWrite,EditAnywhere, Category=Config ,meta=(ClampMin = "0.0" , ClampMax = "1.0")) - float LocalSpaceBlendAlpha = 0.0f; - -}; - -USTRUCT(BlueprintType) -struct FOLSMaskWeights -{ - GENERATED_BODY() - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves", meta=(ClampMin = "0.0", ClampMax = "1.0")) - float MaskWeight = 0; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves", meta=(ClampMin = "0.0", ClampMax = "1.0")) - float MaskAdditive = 0; -}; - -USTRUCT(BlueprintType) -struct FOLSArmMaskWeights -{ - GENERATED_BODY() - -public: - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - EOLSAdditiveMode ArmAdditiveMode = EOLSAdditiveMode::ELocalSpace; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights MaskWeights; - - UPROPERTY(BlueprintReadOnly,Category = "Mask Curves") - float ArmMeshSpaceBlend = 0.0f; - - UPROPERTY(BlueprintReadOnly,Category = "Mask Curves") - float ArmLocalSpaceBlend = 0.0f; -}; - -USTRUCT(BlueprintType) -struct FOLSMaskingWeights -{ - GENERATED_BODY() - -public: - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights LegsWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights PelvisWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights SpineWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights HeadWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSArmMaskWeights RightArmWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights RightHandWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSArmMaskWeights LeftArmWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSMaskWeights LeftHandWeights; - -}; - -USTRUCT(BlueprintType) -struct FOLSCapturedMaskingWeights -{ - GENERATED_BODY() - -public: - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights LegsWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights PelvisWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights SpineWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights HeadWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights RightArmWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights RightHandWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights LeftArmWeights; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Mask Curves") - FOLSNodeMaskWeights LeftHandWeights; - -}; - -USTRUCT(BlueprintType) -struct FOLSMaskAnimation -{ - GENERATED_BODY() - -public: - - UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation") - TObjectPtr Animation = nullptr; - - UPROPERTY(BlueprintReadOnly, Category = "Masking Curves", meta = (HideDefault)) - FOLSCapturedMaskingWeights Weights; - - UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation") - FOLSMaskingWeights MaskingWeights; - - UPROPERTY(BlueprintReadOnly, Category = "Masking Curves", meta = (HideDefault)) - TMap CurvesToModify; - - UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation") - float MaskPoseTime = 0.f; - -public: - -#if WITH_EDITOR - void CacheAdditiveCurves(); -#endif -}; - -USTRUCT(BlueprintType) -struct FOLSGaitMasks -{ - GENERATED_BODY() - -public: - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation") - FOLSMaskAnimation ForwardMask; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation") - FOLSMaskAnimation RightMask; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation") - FOLSMaskAnimation LeftMask; - - UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category = "Animation") - FOLSMaskAnimation BackwardMask; - -public: - -#if WITH_EDITOR - void CacheAdditiveCurves(); -#endif -}; - -USTRUCT(BlueprintType) -struct FOLSStanceMaskSets -{ - GENERATED_BODY() - -public: - -#if WITH_EDITOR - void CacheAdditiveCurves(); -#endif - - const FOLSGaitMasks* SelectGaitMasksByGait(const FGameplayTag& gait); - const FOLSMaskAnimation& GetIdleMask() const; - const FOLSMaskAnimation& GetAimMask() const; - FORCEINLINE void GetAimBlendInOut(float& outBlendIn, float& outBlendOut) const; - -public: - - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets") - TMap GaitMasks; - - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets") - FOLSMaskAnimation IdleMask; - - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets") - FOLSMaskAnimation AimMask; - - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets") - float AimBlendInTime = .4f; - - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Mask Sets") - float AimBlendOutTime = .4f; -}; - -// Legs -static const FName MaskLegsCurveName = FName("LegsMask"); -static const FName MaskLegsLocalSpaceCurveName = FName("LegsMask_LS"); -static const FName MaskLegsMeshSpaceCurveName = FName("LegsMask_MS"); -static const FName MaskLegsAddCurveName = FName("LegsMask_Add"); - -// Pelvis -static const FName MaskPelvisCurveName = FName("PelvisMask"); -static const FName MaskPelvisLocalSpaceCurveName = FName("PelvisMask_LS"); -static const FName MaskPelvisMeshSpaceCurveName = FName("PelvisMask_MS"); -static const FName MaskPelvisAddCurveName = FName("PelvisMask_Add"); - -// Spine -static const FName MaskSpineCurveName = FName("SpineMask"); -static const FName MaskSpineLocalSpaceCurveName = FName("SpineMask_LS"); -static const FName MaskSpineMeshSpaceCurveName = FName("SpineMask_MS"); -static const FName MaskSpineAddCurveName = FName("SpineMask_Add"); - -// Head -static const FName MaskHeadCurveName = FName("HeadMask"); -static const FName MaskHeadLocalSpaceCurveName = FName("HeadMask_LS"); -static const FName MaskHeadMeshSpaceCurveName = FName("HeadMask_MS"); -static const FName MaskHeadAddCurveName = FName("HeadMask_Add"); - -// Right Arm -static const FName MaskRightArmCurveName = FName("RightArmMask"); -static const FName RightArmLocalSpaceCurveName = FName("RightArmMask_LS"); -static const FName RightArmMeshSpaceCurveName = FName("RightArmMask_MS"); -static const FName MaskRightArmAddCurveName = FName("RightArmMask_Add"); - -// Left Arm -static const FName MaskLeftArmCurveName = FName("LeftArmMask"); -static const FName LeftArmLocalSpaceCurveName = FName("LeftArmMask_LS"); -static const FName LeftArmMeshSpaceCurveName = FName("LeftArmMask_MS"); -static const FName MaskLeftArmAddCurveName = FName("LeftArmMask_Add"); - -// Right Hand -static const FName RightHandCurveName = FName("RightHandMask"); -static const FName RightHandLocalSpaceCurveName = FName("RightHandMask_LS"); -static const FName RightHandMeshSpaceCurveName = FName("RightHandMask_MS"); -static const FName MaskRightHandAddCurveName = FName("RightHandMask_Add"); - -// Left Hand -static const FName LeftHandCurveName = FName("LeftHandMask"); -static const FName LeftHandLocalSpaceCurveName = FName("LeftHandMask_LS"); -static const FName LeftHandMeshSpaceCurveName = FName("LeftHandMask_MS"); -static const FName MaskLeftHandAddCurveName = FName("LeftHandMask_Add"); - -// Masking Group -static const FName MaskingGroupName = FName("Standing Mask"); diff --git a/Source/OLSAnimation/Public/Nodes/AnimNode_OLSMask.h b/Source/OLSAnimation/Public/Nodes/AnimNode_OLSMask.h deleted file mode 100644 index 40b9b53..0000000 --- a/Source/OLSAnimation/Public/Nodes/AnimNode_OLSMask.h +++ /dev/null @@ -1,209 +0,0 @@ -// © 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 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 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 LocalSpaceDesiredBoneBlendWeights; - - UPROPERTY() - TArray MeshSpaceDesiredBoneBlendWeights; - - UPROPERTY() - TArray LocalSpaceCurrentBoneBlendWeights; - - UPROPERTY() - TArray MeshSpaceCurrentBoneBlendWeights; - - // Using a more memory-efficient representation for the curves - TBaseBlendedCurve LocalCurvePoseSourceIndices; - TBaseBlendedCurve MeshCurvePoseSourceIndices; -}; - -USTRUCT(BlueprintInternalUseOnly) -struct FOLSPerBoneBlendWeights -{ - GENERATED_BODY() - -public: - - UPROPERTY() - TArray 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 BlendMasks; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Runtime, meta=(PinShownByDefault)) - TArray 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 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 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; -}; diff --git a/Source/OLSAnimation/Public/Nodes/AnimNode_SlotCustom.h b/Source/OLSAnimation/Public/Nodes/AnimNode_SlotCustom.h deleted file mode 100644 index 254c8b6..0000000 --- a/Source/OLSAnimation/Public/Nodes/AnimNode_SlotCustom.h +++ /dev/null @@ -1,21 +0,0 @@ -// © 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 "AnimNodes/AnimNode_Slot.h" -#include "UObject/Object.h" -#include "AnimNode_SlotCustom.generated.h" - -/** - * - */ -USTRUCT(BlueprintInternalUseOnly) -struct OLSANIMATION_API FAnimNode_SlotCustom : public FAnimNode_Slot -{ - GENERATED_BODY() - -public: - - virtual void Update_AnyThread(const FAnimationUpdateContext& context) override; -}; diff --git a/Source/OLSAnimationEditor/Private/Nodes/AnimGraphNode_OLSMask.cpp b/Source/OLSAnimationEditor/Private/Nodes/AnimGraphNode_OLSMask.cpp deleted file mode 100644 index 68ef0d7..0000000 --- a/Source/OLSAnimationEditor/Private/Nodes/AnimGraphNode_OLSMask.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. - - -#include "Nodes/AnimGraphNode_OLSMask.h" - -#include "Kismet2/BlueprintEditorUtils.h" - -#define LOCTEXT_NAMESPACE "OLSNodes" - -UAnimGraphNode_OLSMask::UAnimGraphNode_OLSMask(const FObjectInitializer& objectInitializer) : Super(objectInitializer) -{ - Node.BlendMasks.Reserve(1); - Node.MaskBlendWeights.Reserve(1); - Node.AllBoneBlendWeights.Reserve(1); -} - -FLinearColor UAnimGraphNode_OLSMask::GetNodeTitleColor() const -{ - return FLinearColor(0.0f, 204.0f, 204.0f); -} - -FText UAnimGraphNode_OLSMask::GetTooltipText() const -{ - return LOCTEXT("AnimGraphNode_OLSMask_Tooltip", "OLS Mask Node"); -} - -FText UAnimGraphNode_OLSMask::GetNodeTitle(ENodeTitleType::Type TitleType) const -{ - return LOCTEXT("AnimGraphNode_OLSMaskBlend_Title", "Per Body Part Mask"); -} - -void UAnimGraphNode_OLSMask::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) -{ - const FName PropertyName = (PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None); - - - if (PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FAnimNode_OLSMask, BlendMasks)) - { - FScopedTransaction Transaction(LOCTEXT("AddedBlendMask", "Add Blend Mask")); - Modify(); - - const int32 NumMasks = Node.BlendMasks.Num(); - Node.MaskBlendWeights.SetNum(NumMasks); - Node.AllBoneBlendWeights.SetNum(NumMasks); - FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint()); - ReconstructNode(); - } - - Super::PostEditChangeProperty(PropertyChangedEvent); -} - -FString UAnimGraphNode_OLSMask::GetNodeCategory() const -{ - return TEXT("Blends|OLS Nodes"); -} - -void UAnimGraphNode_OLSMask::PreloadRequiredAssets() -{ - const TObjectPtr animBlueprint = GetAnimBlueprint(); - if (animBlueprint && !GIsCookerLoadingPackage && animBlueprint->TargetSkeleton) - { - const int32 numBlendMasks = Node.BlendMasks.Num(); - if (numBlendMasks > 0) - { - for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) - { - const FName blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; - if (const TObjectPtr blendProfile = animBlueprint->TargetSkeleton->GetBlendProfile( - blendProfileName)) - { - Node.BlendMasks[maskIndex].BlendProfile = blendProfile; - } - - const TObjectPtr blendMask = Node.BlendMasks[maskIndex].BlendProfile; - PreloadObject(blendMask); - } - } - } - - Super::PreloadRequiredAssets(); -} - -void UAnimGraphNode_OLSMask::BakeDataDuringCompilation(FCompilerResultsLog& MessageLog) -{ - const TObjectPtr animBlueprint = GetAnimBlueprint(); - if (!GIsCookerLoadingPackage && animBlueprint->TargetSkeleton) - { - const int32 numBlendMasks = Node.BlendMasks.Num(); - for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) - { - const FOLSMaskSettings& currentMask = Node.BlendMasks[maskIndex]; - const FName& blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; - if (const TObjectPtr bendProfile = animBlueprint->TargetSkeleton->GetBlendProfile( - blendProfileName)) - { - Node.BlendMasks[maskIndex].BlendProfile = bendProfile; - } - - if (currentMask.bShouldAddSlot) - { - animBlueprint->TargetSkeleton->RegisterSlotNode(currentMask.SlotName); - } - } - } -} - -void UAnimGraphNode_OLSMask::ValidateAnimNodeDuringCompilation(USkeleton* skeleton, FCompilerResultsLog& MessageLog) -{ - if (skeleton) - { - // ensure to cache the per-bone blend weights - if (!Node.ArePerBoneBlendWeightsValid(skeleton)) - { - Node.RebuildPerBoneBlendWeights(skeleton); - } - - if (Node.BlendMasks.Num() > 0) - { - const int32 numBlendMasks = Node.BlendMasks.Num(); - for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) - { - const FName& blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; - const TObjectPtr blendProfile = skeleton->GetBlendProfile(blendProfileName); - if (blendProfile) - { - Node.BlendMasks[maskIndex].BlendProfile = blendProfile; - } - - if (!blendProfile) - { - MessageLog.Error( - *FText::Format( - LOCTEXT("BlendProfileIsNull", "@@ has null BlendMask In Index {0}. "), - FText::AsNumber(maskIndex)).ToString(), this, blendProfile); - continue; - } - if (!blendProfile->IsBlendMask()) - { - MessageLog.Error( - *FText::Format(LOCTEXT("BlendProfileModeError", - "@@ is using a BlendProfile(@@) without a BlendMask mode In Index {0}. "), FText::AsNumber( - maskIndex)).ToString(), this, blendProfile); - } - } - } - } - Super::ValidateAnimNodeDuringCompilation(skeleton, MessageLog); -} - -#undef LOCTEXT_NAMESPACE diff --git a/Source/OLSAnimationEditor/Public/Nodes/AnimGraphNode_OLSMask.h b/Source/OLSAnimationEditor/Public/Nodes/AnimGraphNode_OLSMask.h deleted file mode 100644 index 719f1a1..0000000 --- a/Source/OLSAnimationEditor/Public/Nodes/AnimGraphNode_OLSMask.h +++ /dev/null @@ -1,44 +0,0 @@ -// © 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 "AnimGraphNode_Base.h" -#include "Nodes/AnimNode_OLSMask.h" -#include "AnimGraphNode_OLSMask.generated.h" - -/** - * - */ -UCLASS(MinimalAPI) -class UAnimGraphNode_OLSMask : public UAnimGraphNode_Base -{ - GENERATED_BODY() - -public: - - UAnimGraphNode_OLSMask(const FObjectInitializer& objectInitializer); - -private: - - // UEdGraphNode interface - virtual FLinearColor GetNodeTitleColor() const override; - virtual FText GetTooltipText() const override; - virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; - virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override; - // End of UEdGraphNode interface - - // UAnimGraphNode_Base interface - virtual FString GetNodeCategory() const override; - virtual void PreloadRequiredAssets() override; - virtual void BakeDataDuringCompilation(class FCompilerResultsLog& MessageLog) override; - // End of UAnimGraphNode_Base interface - - // Gives each visual node a chance to validate that they are still valid in the context of the compiled class, giving a last shot at error or warning generation after primary compilation is finished - virtual void ValidateAnimNodeDuringCompilation(class USkeleton* skeleton, class FCompilerResultsLog& MessageLog) override; - // End of UAnimGraphNode_Base interface - -private: - UPROPERTY(EditAnywhere, Category=Settings) - FAnimNode_OLSMask Node; -};