void FAnimationNode_TwoWayBlend::Update(const FAnimationUpdateContext& Context) { EvaluateGraphExposedInputs.Execute(Context); const float ActualAlpha = AlphaScaleBias.ApplyTo(Alpha); if (ActualAlpha > ZERO_ANIMWEIGHT_THRESH) { if (ActualAlpha < 1.0f - ZERO_ANIMWEIGHT_THRESH) { // Blend A and B together A.Update(Context.FractionalWeight(1.0f - ActualAlpha)); B.Update(Context.FractionalWeight(ActualAlpha)); } else { // Take all of B B.Update(Context); } } else { // Take all of A A.Update(Context); } }
void FAnimNode_StateMachine::UpdateTransitionStates(const FAnimationUpdateContext& Context, FAnimationActiveTransitionEntry& Transition) { if (Transition.bActive) { switch (Transition.LogicType) { case ETransitionLogicType::TLT_StandardBlend: { // update both states UpdateState(Transition.PreviousState, Context.FractionalWeight(1.0f - Transition.Alpha)); UpdateState(Transition.NextState, Context.FractionalWeight(Transition.Alpha)); } break; case ETransitionLogicType::TLT_Custom: { if (Transition.CustomTransitionGraph.LinkID != INDEX_NONE) { Transition.CustomTransitionGraph.Update(Context); for (TArray<FAnimNode_TransitionPoseEvaluator*>::TIterator PoseEvaluatorListIt = Transition.PoseEvaluators.CreateIterator(); PoseEvaluatorListIt; ++PoseEvaluatorListIt) { FAnimNode_TransitionPoseEvaluator* Evaluator = *PoseEvaluatorListIt; if (Evaluator->InputNodeNeedsUpdate()) { const bool bUsePreviousState = (Evaluator->DataSource == EEvaluatorDataSource::EDS_SourcePose); const int32 EffectiveStateIndex = bUsePreviousState ? Transition.PreviousState : Transition.NextState; UpdateState(EffectiveStateIndex, Context); } } } } break; default: break; } } }
void FAnimNode_ApplyMeshSpaceAdditive::Update(const FAnimationUpdateContext& Context) { Base.Update(Context); ActualAlpha = 0.f; if (IsLODEnabled(Context.AnimInstanceProxy, LODThreshold)) { // @note: If you derive this class, and if you have input that you rely on for base // this is not going to work EvaluateGraphExposedInputs.Execute(Context); ActualAlpha = AlphaScaleBias.ApplyTo(Alpha); if (FAnimWeight::IsRelevant(ActualAlpha)) { Additive.Update(Context.FractionalWeight(ActualAlpha)); } } }
void FAnimNode_BlendListBase::Update(const FAnimationUpdateContext& Context) { EvaluateGraphExposedInputs.Execute(Context); const int NumPoses = BlendPose.Num(); checkSlow((BlendTime.Num() == NumPoses) && (BlendWeights.Num() == NumPoses)); if (NumPoses > 0) { // Handle a change in the active child index; adjusting the target weights const int32 ChildIndex = GetActiveChildIndex(); if (ChildIndex != LastActiveChildIndex) { bool LastChildIndexIsInvalid = (LastActiveChildIndex == INDEX_NONE); LastActiveChildIndex = ChildIndex; const float CurrentWeight = BlendWeights[ChildIndex]; const float DesiredWeight = 1.0f; const float WeightDifference = FMath::Clamp<float>(FMath::Abs<float>(DesiredWeight - CurrentWeight), 0.0f, 1.0f); // scale by the weight difference since we want always consistency: // - if you're moving from 0 to full weight 1, it will use the normal blend time // - if you're moving from 0.5 to full weight 1, it will get there in half the time const float RemainingBlendTime = LastChildIndexIsInvalid ? 0.0f : ( BlendTime[ChildIndex] * WeightDifference ); for (int32 i = 0; i < RemainingBlendTimes.Num(); ++i) { RemainingBlendTimes[i] = RemainingBlendTime; } } // Advance the weights //@TODO: This means we advance even in a frame where the target weights/times just got modified; is that desirable? float SumWeight = 0.0f; for (int32 i = 0; i < RemainingBlendTimes.Num(); ++i) { float& RemainingBlendTime = RemainingBlendTimes[i]; float& BlendWeight = BlendWeights[i]; const float DesiredWeight = (i == ChildIndex) ? 1.0f : 0.0f; FAnimationRuntime::TickBlendWeight(Context.GetDeltaTime(), DesiredWeight, BlendWeight, RemainingBlendTime); SumWeight += BlendWeight; } // Renormalize the weights if ((SumWeight > ZERO_ANIMWEIGHT_THRESH) && (FMath::Abs<float>(SumWeight - 1.0f) > ZERO_ANIMWEIGHT_THRESH)) { float ReciprocalSum = 1.0f / SumWeight; for (int32 i = 0; i < BlendWeights.Num(); ++i) { BlendWeights[i] *= ReciprocalSum; } } // Update our active children for (int32 i = 0; i < BlendPose.Num(); ++i) { const float BlendWeight = BlendWeights[i]; if (BlendWeight > ZERO_ANIMWEIGHT_THRESH) { BlendPose[i].Update(Context.FractionalWeight(BlendWeight)); } } } }