Files
UnrealEngine/Engine/Source/Runtime/MovieScene/Public/Evaluation/MovieSceneEvalTemplate.h
2025-05-18 13:04:45 +08:00

270 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CoreTypes.h"
#include "Evaluation/MovieSceneCompletionMode.h"
#include "Evaluation/MovieSceneEvalTemplateBase.h"
#include "Evaluation/MovieSceneExecutionTokens.h"
#include "Evaluation/MovieScenePlayback.h"
#include "Evaluation/PersistentEvaluationData.h"
#include "Math/Range.h"
#include "Misc/AssertionMacros.h"
#include "Misc/FrameNumber.h"
#include "Misc/FrameTime.h"
#include "Misc/InlineValue.h"
#include "MovieSceneSection.h"
#include "Templates/Decay.h"
#include "Templates/EnableIf.h"
#include "Templates/PointerIsConvertibleFromTo.h"
#include "Templates/UnrealTemplate.h"
#include "Templates/UnrealTypeTraits.h"
#include "UObject/Class.h"
#include "UObject/ObjectMacros.h"
#include "UObject/WeakObjectPtr.h"
#include "UObject/WeakObjectPtrTemplates.h"
#include "MovieSceneEvalTemplate.generated.h"
class FArchive;
class IMovieScenePlayer;
class UObject;
struct FMovieSceneEvaluationOperand;
struct FMovieSceneExecutionTokens;
struct FMovieSceneInterrogationData;
/**
* Structure used for movie scene evaluation templates contained within a track. Typically these are defined as one per-section.
* Serialized into a FMovieSceneEvaluationTemplate contained within the sequence itself (for fast initialization at runtime).
* Templates are executed in a 3-phase algorithm:
* 1) Initialize: (opt-in) Called at the start of the frame. Able to access mutable state from the playback context. Used to initialize any persistent state required for the evaluation pass.
* 2) Evaluate: Potentially called on a thread. Should (where possible) perform all costly evaluation logic, accumulating into execution tokens which will be executed at a later time on the game thread.
* 3) Execute: Called on all previously submitted execution tokens to apply the evaluated state to the movie scene player
*/
USTRUCT()
struct FMovieSceneEvalTemplate : public FMovieSceneEvalTemplateBase
{
public:
GENERATED_BODY()
/**
* Default Constructor
*/
FMovieSceneEvalTemplate()
{
CompletionMode = EMovieSceneCompletionMode::KeepState;
}
/**
* Check whether this template mandates Initialize being called.
* Defines whether a pointer to this track will be added to the initialization section of template evaluation.
* @return Boolean representing whether this template mandates Initialize being called
*/
bool RequiresInitialization() const
{
return (OverrideMask & RequiresInitializeFlag) != 0;
}
/**
* Check whether we should restore any pre-animated state that was supplied by this template when it is no longer evaluated
* @note Pre-animated state bound to evaluation templates is reference counted across all similar animation types for a given object.
* This ensures that pre-animated state restores correctly for overlapping templates.
*/
EMovieSceneCompletionMode GetCompletionMode() const
{
return CompletionMode;
}
/**
* Set this template's completion mode
* @note Pre-animated state bound to evaluation templates is reference counted across all similar animation types for a given object.
* This ensures that pre-animated state restores correctly for overlapping templates.
*/
void SetCompletionMode(EMovieSceneCompletionMode InCompletionMode)
{
CompletionMode = InCompletionMode;
}
/**
* Initialize this template, copying any data required for evaluation into the specified state block.
* @note This function is intended to allow pre-frame set up, and should avoid mutating any state.
* Only called if EnableOverrides(RequiresInitializeFlag) has been called.
*
* @param Operand Unique handle to the operand on which we are to operate. May represent multiple objects. Resolve through IMovieScenePlayer::FindBoundObjects(Operand)
* @param Context Evaluation context specifying the current evaluation time, sub sequence transform and other relevant information.
* @param PersistentData Persistent data store which can be used to store arbitrary data pertaining to the current template that may be required in Evaluate(Swept)
* @param Player The movie scene player currently playing back this sequence
*/
virtual void Initialize(const FMovieSceneEvaluationOperand& Operand, const FMovieSceneContext& Context, FPersistentEvaluationData& PersistentData, IMovieScenePlayer& Player) const
{
ensureMsgf(false, TEXT("FMovieSceneEvalTemplate::Initialize has not been implemented. Verify EnableOverrides() usage is correct or implement this function."));
}
/**
* Evaluate this template, adding any execution tokens to the specified list
* @note Only called when the containing template has an evaluation method of EEvaluationMethod::Static
* This function should perform any expensive or costly evaluation logic required to calculate the final animated state.
* Potentially called on a thread, and as such has no access to the current evaluation environment.
*
* @param Operand Unique handle to the operand on which we are to operate. Only to be used as a reference, or forwarded throgh to an execution token.
* @param Context Evaluation context specifying the current evaluation time, sub sequence transform and other relevant information.
* @param PersistentData Persistent data store which can be used to access arbitrary data pertaining to the current template that should have been set up in initialize.
* @param ExecutionTokens Stack of execution tokens that will be used to apply animated state to the environment at a later time.
*/
virtual void Evaluate(const FMovieSceneEvaluationOperand& Operand, const FMovieSceneContext& Context, const FPersistentEvaluationData& PersistentData, FMovieSceneExecutionTokens& ExecutionTokens) const
{
ensureMsgf(false, TEXT("FMovieSceneEvalTemplate::Evaluate has not been implemented. Verify that this template's evaluation track has correct evaluation method (usually set in UMovieSceneTrack::PostCompile), or implement this function."));
}
/**
* Evaluate this template over the given swept range, adding any execution tokens to the specified list.
* @note Only called when the containing template has an evaluation method of EEvaluationMethod::Swept
* This function should perform any expensive or costly evaluation logic required to calculate the final animated state.
* Potentially called on a thread, and as such has no access to the current evaluation environment.
*
* @param Operand Unique handle to the operand on which we are to operate. Only to be used as a reference, or forwarded throgh to an execution token.
* @param Context Evaluation context specifying the current evaluation time, sub sequence transform and other relevant information.
* @param SweptRange The range this is to be swept in this evaluation - always fully contained by the context's range
* @param PersistentData Persistent data store which can be used to access arbitrary data pertaining to the current template that should have been set up in initialize.
* @param ExecutionTokens Stack of execution tokens that will be used to apply animated state to the environment at a later time.
*/
virtual void EvaluateSwept(const FMovieSceneEvaluationOperand& Operand, const FMovieSceneContext& Context, const TRange<FFrameNumber>& SweptRange, const FPersistentEvaluationData& PersistentData, FMovieSceneExecutionTokens& ExecutionTokens) const
{
ensureMsgf(false, TEXT("FMovieSceneEvalTemplate::EvaluateSwept has not been implemented. Verify that this template's evaluation track has correct evaluation method (usually set in UMovieSceneTrack::PostCompile), or implement this function."));
}
/**
* Interrogate this template for its output. Should not have any side effects.
*
* @param Context Evaluation context specifying the current evaluation time, sub sequence transform and other relevant information.
* @param Container Container to populate with the desired output from this track
* @param BindingOverride Optional binding to specify the object that is being animated by this track
*/
virtual void Interrogate(const FMovieSceneContext& Context, FMovieSceneInterrogationData& Container, UObject* BindingOverride) const
{
}
/**
* Interrogate this template for its output. Should not have any side effects.
*
* @param Context Evaluation context specifying the current evaluation time, sub sequence transform and other relevant information.
* @param SweptRange The range to sweep, where this template evaluates with 'swept' evaluation
* @param Container Container to populate with the desired output from this track
* @param BindingOverride Optional binding to specify the object that is being animated by this track
*/
virtual void Interrogate(const FMovieSceneContext& Context, TRange<FFrameNumber> SweptRange, FMovieSceneInterrogationData& Container, UObject* BindingOverride) const
{
}
public:
/**
* Set the source section from which this template originated
*
* @param SourceSection The source section
*/
void SetSourceSection(const UMovieSceneSection* InSourceSection)
{
SourceSectionPtr = InSourceSection;
}
/**
* Get the source section from which this template originated
*
* @return The source section from which this template originated
*/
const UMovieSceneSection* GetSourceSection() const
{
return SourceSectionPtr.Get();
}
protected:
/**
* Evaluate this template's easing functions based on the specified time
*/
MOVIESCENE_API float EvaluateEasing(FFrameTime CurrentTime) const;
/**
* Enum evaluation flag structure defining which functions are to be called in implementations of this struct
*/
enum EOverrideMask
{
RequiresInitializeFlag = 0x004,
};
/** Enumeration value signifying whether we should restore any animated state stored by this entity when this eval tempalte is no longer evaluated */
UPROPERTY()
EMovieSceneCompletionMode CompletionMode;
/** The section from which this template originates */
UPROPERTY()
TWeakObjectPtr<const UMovieSceneSection> SourceSectionPtr;
};
/**
* Custom serialized type that allows serializing structs derived from FMovieSceneEvalTemplate, and attempts to store an evaluation template in inline memory if possible
*/
USTRUCT()
struct FMovieSceneEvalTemplatePtr
#if CPP
: TInlineValue<FMovieSceneEvalTemplate, 128>
#endif
{
GENERATED_BODY()
/** Default construction to an empty container */
FMovieSceneEvalTemplatePtr(){}
/** Construction from any FMovieSceneEvalTemplate derivative */
template<
typename T,
typename = typename TEnableIf<TPointerIsConvertibleFromTo<typename TDecay<T>::Type, FMovieSceneEvalTemplate>::Value>::Type
>
FMovieSceneEvalTemplatePtr(T&& In)
: TInlineValue(Forward<T>(In))
{
static_assert(!std::is_same_v<typename TDecay<T>::Type, FMovieSceneEvalTemplate>, "Direct usage of FMovieSceneEvalTemplate is prohibited.");
#if WITH_EDITOR
checkf(T::StaticStruct() == &In.GetScriptStruct() && T::StaticStruct() != FMovieSceneEvalTemplate::StaticStruct(), TEXT("%s does not correctly override GetScriptStructImpl. Template will not serialize correctly."), *T::StaticStruct()->GetName());
#endif
}
/** Copy construction/assignment */
FMovieSceneEvalTemplatePtr(const FMovieSceneEvalTemplatePtr& RHS)
{
*this = RHS;
}
FMovieSceneEvalTemplatePtr& operator=(const FMovieSceneEvalTemplatePtr& RHS)
{
if (RHS.IsValid())
{
UScriptStruct::ICppStructOps& StructOps = *RHS->GetScriptStruct().GetCppStructOps();
void* Allocation = Reserve(StructOps.GetSize(), StructOps.GetAlignment());
StructOps.Construct(Allocation);
StructOps.Copy(Allocation, &RHS.GetValue(), 1);
}
else
{
Reset();
}
return *this;
}
/** Templates are moveable */
FMovieSceneEvalTemplatePtr(FMovieSceneEvalTemplatePtr&&) = default;
FMovieSceneEvalTemplatePtr& operator=(FMovieSceneEvalTemplatePtr&&) = default;
/** Serialize the template */
MOVIESCENE_API bool Serialize(FArchive& Ar);
};
template<> struct TStructOpsTypeTraits<FMovieSceneEvalTemplatePtr> : public TStructOpsTypeTraitsBase2<FMovieSceneEvalTemplatePtr>
{
enum { WithSerializer = true, WithCopy = true };
};