Files
UnrealEngineUWP/Engine/Source/Runtime/AnimGraphRuntime/Public/AnimNodes/AnimNode_RandomPlayer.h
koray hagen 26af906499 Graph-driven pose warping, with root motion delta flow:
1) Root motion delta flow supported through all anim nodes deriving from FAnimNode_AssetPlayerBase and montages.
2) Stride/Orientation warping feature graph-driven evaluation modes which leverage root motion delta flow (graph-driven slope warping currently disabled).
3) Root motion flow connected to the Animation Warping plugin.
4) Pose Warping test map featuring various motion "styles" connected to pose warping (Motion Matching, Blend Space Graphs/Assets, Sequence Players, Evaluators).

#preflight 6092380a58c4790001a3e9b6
#rb aaron.cox, braeden.shosa, thomas.sarkanen
#jira none
#fyi laurent.delayen

[CL 16208667 by koray hagen in ue5-main branch]
2021-05-05 12:18:35 -04:00

163 lines
5.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "AlphaBlend.h"
#include "Animation/AnimNodeBase.h"
#include "Animation/AnimationAsset.h"
#include "CoreMinimal.h"
#include "Math/RandomStream.h"
#include "UObject/ObjectMacros.h"
#include "AnimNode_RandomPlayer.generated.h"
enum class ERandomDataIndexType
{
Current,
Next,
};
/** The random player node holds a list of sequences and parameter ranges which will be played continuously
* In a random order. If shuffle mode is enabled then each entry will be played once before repeating any
*/
USTRUCT(BlueprintInternalUseOnly)
struct FRandomPlayerSequenceEntry
{
GENERATED_BODY()
FRandomPlayerSequenceEntry()
: Sequence(nullptr)
, ChanceToPlay(1.0f)
, MinLoopCount(0)
, MaxLoopCount(0)
, MinPlayRate(1.0f)
, MaxPlayRate(1.0f)
{
}
/** Sequence to play when this entry is picked */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings")
TObjectPtr<UAnimSequence> Sequence;
/** When not in shuffle mode, this is the chance this entry will play (normalized against all other sample chances) */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings", meta = (UIMin = "0", ClampMin = "0"))
float ChanceToPlay;
/** Minimum number of times this entry will loop before ending */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings", meta = (UIMin = "0", ClampMin = "0"))
int32 MinLoopCount;
/** Maximum number of times this entry will loop before ending */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings", meta = (UIMin = "0", ClampMin = "0"))
int32 MaxLoopCount;
/** Minimum playrate for this entry */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings", meta = (UIMin = "0", ClampMin = "0"))
float MinPlayRate;
/** Maximum playrate for this entry */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings", meta = (UIMin = "0", ClampMin = "0"))
float MaxPlayRate;
/** Blending properties used when this entry is blending in ontop of another entry */
UPROPERTY(EditAnywhere, Category = "Settings")
FAlphaBlend BlendIn;
};
struct FRandomAnimPlayData
{
// Index into the real sequence entry list, not the valid entry list.
FRandomPlayerSequenceEntry* Entry = nullptr;
// The time at which the animation started playing. Used to initialize
// the play for this animation and detect when a loop has occurred.
float PlayStartTime = 0.0f;
// The time at which the animation is currently playing.
float CurrentPlayTime = 0.0f;
// Delta time record for this play through
FDeltaTimeRecord DeltaTimeRecord;
// Calculated play rate
float PlayRate = 0.0f;
// Current blend weight
float BlendWeight = 0.0f;
// Calculated loops remaining
int32 RemainingLoops = 0;
// Marker tick record for this play through
FMarkerTickRecord MarkerTickRecord;
};
USTRUCT(BlueprintInternalUseOnly)
struct ANIMGRAPHRUNTIME_API FAnimNode_RandomPlayer : public FAnimNode_Base
{
GENERATED_BODY()
FAnimNode_RandomPlayer();
public:
/** List of sequences to randomly step through */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings")
TArray<FRandomPlayerSequenceEntry> Entries;
// FAnimNode_Base interface
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
virtual void Evaluate_AnyThread(FPoseContext& Output) override;
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
// End of FAnimNode_Base interface
private:
// Return the index of the next FRandomPlayerSequenceEntry to play, from the list
// of valid playable entries (ValidEntries).
int32 GetNextValidEntryIndex();
// Return the play data for either the currently playing animation or the next
// animation to blend into.
FRandomAnimPlayData& GetPlayData(ERandomDataIndexType Type);
// Initialize the play data with the given index into the ValidEntries array and
// a specific blend weight. All other member data will be reset to their default values.
void InitPlayData(FRandomAnimPlayData& Data, int32 ValidEntryIndex, float BlendWeight);
// Advance to the next playable sequence. This is only called once a sequence is fully
// blended or there's a hard switch to the same playable entry.
void AdvanceToNextSequence();
// Build a new ShuffleList array, which is a shuffled index list of all the valid
// playable entries in ValidEntries. The LastEntry can be set to a valid entry index to
// ensure that the top/last item in the shuffle list will be a different value from it;
// pass in INDEX_NONE to disable the check.
void BuildShuffleList(int32 LastEntry);
// List of valid sequence entries
TArray<FRandomPlayerSequenceEntry*> ValidEntries;
// Normalized list of play chances when we aren't using shuffle mode
TArray<float> NormalizedPlayChances;
// Play data for the current and next sequence
TArray<FRandomAnimPlayData> PlayData;
// Index of the 'current' data set in the PlayData array.
int32 CurrentPlayDataIndex;
// List to store transient shuffle stack in shuffle mode.
TArray<int32> ShuffleList;
// Random number source
FRandomStream RandomStream;
public:
/** When shuffle mode is active we will never loop a sequence beyond MaxLoopCount
* without visiting each sequence in turn (no repeats). Enabling this will ignore
* ChanceToPlay for each entry
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings")
bool bShuffleMode;
};