Files
UnrealEngineUWP/Engine/Source/Runtime/AnimGraphRuntime/Private/SequencePlayerLibrary.cpp
koray hagen 7952f73fdc #preflight 6143ef4681695600011c49a8
#rb braeden.shosa, aaron.cox, cesar.castro
#jira none

Motion Trajectory Component for Motion Matching:

Motion Trajectory Component notes:
1) Abstract component/interface implemented with prediction and history API.
2) Implemented uniform, frame-rate independent history sampling algorithm for retaining trajectory sample coherence.
3) Implemented concrete Character Movement Trajectory Component for encapsulating ground locomotion prediction algorithm and API.
4) Motion Trajectory blueprint library containing:
5) FlattenTrajectory2D algorithm for isolating and removing Z axis direction contribution from tracjectory.
6) ClampTrajectoryDirection for projecting trajectory samples into a discrete, allowed set of directions (such as cardinal).

Engine changes:
1) Implemented shared TrajectorySample, Range, and Domain structures for common usage among Motion Trajectory, Pose Search, and Blueprint.
2) Expanded Sequence Player blueprint library functionality for Scripted Motion Matching content example.

Pose Search changes:
1) Match Pose renamed to Pose History with minor configuration parameters.
2) Complete removal of approximated past trajectory sampling. This has now been pushed to the Motion Trajectory Component.
3) Motion Matching interface changes: Goal has been replaced with Trajectory and Dynamic Play Rate Adjustment has been encapsulated to an experimental code module and blueprint library. New defaults, and encapsulating settings.
4) Motion Matching changes: New Pose Search blueprint library which encapsulates core Motion Matching algorithm.
5) Unified Trajectory to Pose Feature Vector transformation algorithms.
6) Removal of temporary Pose Search Prediction blueprint library (now Dynamic Play Rate).
7) End-to-end implementation support for Past/Future Time and Distance domain schemas.

AnimInput changes:
1) Removal of AnimInput_CapsulePrediction (replaced with Motion Trajectory Component).

Gameplay Anim Gym changes:
1) Pose search database is now fully distance-based (history and future).
2) Character blueprint includes Character Movement Trajectory Component with distance-based domain setup.
3) Scripted Motion Matching anim node function prototype with Engine content example.
#preflight 6143ef4681695600011c49a8

#ROBOMERGE-AUTHOR: koray.hagen
#ROBOMERGE-SOURCE: CL 17547347 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530)

[CL 17547352 by koray hagen in ue5-release-engine-test branch]
2021-09-16 22:34:27 -04:00

168 lines
5.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SequencePlayerLibrary.h"
#include "Animation/AnimNode_Inertialization.h"
#include "Animation/AnimNode_SequencePlayer.h"
DEFINE_LOG_CATEGORY_STATIC(LogSequencePlayerLibrary, Verbose, All);
FSequencePlayerReference USequencePlayerLibrary::ConvertToSequencePlayer(const FAnimNodeReference& Node, EAnimNodeReferenceConversionResult& Result)
{
return FAnimNodeReference::ConvertToType<FSequencePlayerReference>(Node, Result);
}
FSequencePlayerReference USequencePlayerLibrary::SetAccumulatedTime(const FSequencePlayerReference& SequencePlayer, float Time)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("SetAccumulatedTime"),
[Time](FAnimNode_SequencePlayer& InSequencePlayer)
{
InSequencePlayer.SetAccumulatedTime(Time);
});
return SequencePlayer;
}
FSequencePlayerReference USequencePlayerLibrary::SetStartPosition(const FSequencePlayerReference& SequencePlayer, float StartPosition)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("SetStartPosition"),
[StartPosition](FAnimNode_SequencePlayer& InSequencePlayer)
{
if(!InSequencePlayer.SetStartPosition(StartPosition))
{
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not set start position on sequence player, value is not dynamic. Set it as Always Dynamic."));
}
});
return SequencePlayer;
}
FSequencePlayerReference USequencePlayerLibrary::SetPlayRate(const FSequencePlayerReference& SequencePlayer, float PlayRate)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("SetPlayRate"),
[PlayRate](FAnimNode_SequencePlayer& InSequencePlayer)
{
if(!InSequencePlayer.SetPlayRate(PlayRate))
{
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not set play rate on sequence player, value is not dynamic. Set it as Always Dynamic."));
}
});
return SequencePlayer;
}
FSequencePlayerReference USequencePlayerLibrary::SetSequence(const FSequencePlayerReference& SequencePlayer, UAnimSequenceBase* Sequence)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("SetSequence"),
[Sequence](FAnimNode_SequencePlayer& InSequencePlayer)
{
if(!InSequencePlayer.SetSequence(Sequence))
{
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not set sequence on sequence player, value is not dynamic. Set it as Always Dynamic."));
}
});
return SequencePlayer;
}
FSequencePlayerReference USequencePlayerLibrary::SetSequenceWithInertialBlending(const FAnimUpdateContext& UpdateContext, const FSequencePlayerReference& SequencePlayer, UAnimSequenceBase* Sequence, float BlendTime)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("SetSequenceWithInterialBlending"),
[Sequence, &UpdateContext, BlendTime](FAnimNode_SequencePlayer& InSequencePlayer)
{
const UAnimSequenceBase* CurrentSequence = InSequencePlayer.GetSequence();
const bool bAnimSequenceChanged = (CurrentSequence != Sequence);
if(!InSequencePlayer.SetSequence(Sequence))
{
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not set sequence on sequence player, value is not dynamic. Set it as Always Dynamic."));
}
if(bAnimSequenceChanged && BlendTime > 0.0f)
{
if (const FAnimationUpdateContext* AnimationUpdateContext = UpdateContext.GetContext())
{
if (UE::Anim::IInertializationRequester* InertializationRequester = AnimationUpdateContext->GetMessage<UE::Anim::IInertializationRequester>())
{
InertializationRequester->RequestInertialization(BlendTime);
}
}
else
{
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("SetSequenceWithInertialBlending called with invalid context"));
}
}
});
return SequencePlayer;
}
float USequencePlayerLibrary::GetAccumulatedTime(const FSequencePlayerReference& SequencePlayer)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("GetAccumulatedTime"),
[](FAnimNode_SequencePlayer& InSequencePlayer)
{
return InSequencePlayer.GetAccumulatedTime();
});
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not get accumulated time on sequence player."));
return 0.f;
}
float USequencePlayerLibrary::GetStartPosition(const FSequencePlayerReference& SequencePlayer)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("GetStartPosition"),
[](FAnimNode_SequencePlayer& InSequencePlayer)
{
return InSequencePlayer.GetStartPosition();
});
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not get start position on sequence player."));
return 0.f;
}
float USequencePlayerLibrary::GetPlayRate(const FSequencePlayerReference& SequencePlayer)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("GetPlayRate"),
[](FAnimNode_SequencePlayer& InSequencePlayer)
{
return InSequencePlayer.GetPlayRate();
});
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not get play rate on sequence player."));
return 1.f;
}
bool USequencePlayerLibrary::GetLoopAnimation(const FSequencePlayerReference& SequencePlayer)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("GetLoopAnimation"),
[](FAnimNode_SequencePlayer& InSequencePlayer)
{
return InSequencePlayer.GetLoopAnimation();
});
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not get looping state on sequence player."));
return false;
}
UAnimSequenceBase* USequencePlayerLibrary::GetSequence(const FSequencePlayerReference& SequencePlayer)
{
SequencePlayer.CallAnimNodeFunction<FAnimNode_SequencePlayer>(
TEXT("GetSequence"),
[](FAnimNode_SequencePlayer& InSequencePlayer)
{
return InSequencePlayer.GetSequence();
});
UE_LOG(LogSequencePlayerLibrary, Warning, TEXT("Could not get sequence on sequence player."));
return nullptr;
}