Removed files
This commit is contained in:
parent
27ce0e7c26
commit
b7c20351c8
@ -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<FGameplayTag, FOLSGaitMasks>& 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;
|
||||
}
|
@ -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<UBlendProfile> 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<FCompactPose> lsTargetBlendPoses;
|
||||
lsTargetBlendPoses.SetNum(1);
|
||||
|
||||
TArray<FCompactPose> msTargetBlendPoses;
|
||||
msTargetBlendPoses.SetNum(1);
|
||||
|
||||
TArray<FBlendedCurve> lsTargetBlendCurves;
|
||||
lsTargetBlendCurves.SetNum(1);
|
||||
|
||||
TArray<FBlendedCurve> msTargetBlendCurves;
|
||||
msTargetBlendCurves.SetNum(1);
|
||||
|
||||
TArray<UE::Anim::FStackAttributeContainer> lsTargetBlendAttributes;
|
||||
lsTargetBlendAttributes.SetNum(1);
|
||||
|
||||
TArray<UE::Anim::FStackAttributeContainer> 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<float> lsDesiredBlendWeight;
|
||||
lsDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha);
|
||||
TArray<float> 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<UBlendProfile*> 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<FBoneIndexType>& 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<float> lsDesiredBlendWeight;
|
||||
lsDesiredBlendWeight.Add(MaskBlendWeights[maskIndex].LocalSpaceBlendAlpha);
|
||||
TArray<float> 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);
|
||||
}
|
@ -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<UE::Anim::IInertializationRequester>();
|
||||
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
|
||||
}
|
@ -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<class UAnimSequence> 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<FName, float> 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<FGameplayTag, FOLSGaitMasks> 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");
|
@ -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<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;
|
||||
};
|
@ -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;
|
||||
};
|
@ -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<UAnimBlueprint> 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<UBlendProfile> blendProfile = animBlueprint->TargetSkeleton->GetBlendProfile(
|
||||
blendProfileName))
|
||||
{
|
||||
Node.BlendMasks[maskIndex].BlendProfile = blendProfile;
|
||||
}
|
||||
|
||||
const TObjectPtr<UBlendProfile> blendMask = Node.BlendMasks[maskIndex].BlendProfile;
|
||||
PreloadObject(blendMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Super::PreloadRequiredAssets();
|
||||
}
|
||||
|
||||
void UAnimGraphNode_OLSMask::BakeDataDuringCompilation(FCompilerResultsLog& MessageLog)
|
||||
{
|
||||
const TObjectPtr<UAnimBlueprint> 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<UBlendProfile> 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<UBlendProfile> 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
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user