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

345 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Compilation/MovieSceneCompiledDataID.h"
#include "CoreTypes.h"
#include "EntitySystem/MovieSceneSequenceInstanceHandle.h"
#include "Evaluation/MovieSceneEvaluationOperand.h"
#include "Evaluation/MovieScenePlaybackCapabilities.h"
#include "Evaluation/MovieScenePreAnimatedState.h"
#include "MovieSceneSequenceID.h"
#define UE_API MOVIESCENE_API
class UMovieSceneSequence;
class FMovieSceneEntitySystemRunner;
class UMovieSceneCompiledDataManager;
class UMovieSceneEntitySystemLinker;
struct FMovieSceneObjectCache;
struct FMovieSceneSequenceHierarchy;
namespace UE::MovieScene
{
/**
* Parameter structure for initializing a new shared playback state.
*/
struct FSharedPlaybackStateCreateParams
{
/**
* The playback context in which the root sequence will be evaluated.
*/
UObject* PlaybackContext = nullptr;
/**
* The handle of the root sequence instance, if the created playback state
* is meant to relate to an instance that has also been created inside
* a runner/linker's instance registry.
*/
FRootInstanceHandle RootInstanceHandle;
/**
* The linker that will be evaluating the sequence that the created playback
* state relates to.
*/
TObjectPtr<UMovieSceneEntitySystemLinker> Linker;
/**
* The compiled data manager with which the root sequence was compiled, or
* will be compiled. If unset, the default global manager will be used.
*/
UMovieSceneCompiledDataManager* CompiledDataManager = nullptr;
};
/**
* A structure that stores playback state for an entire sequence hierarchy.
*/
struct FSharedPlaybackState : TSharedFromThis<FSharedPlaybackState>
{
public:
UE_API FSharedPlaybackState(UMovieSceneEntitySystemLinker* InLinker = nullptr);
UE_API FSharedPlaybackState(
UMovieSceneSequence& InRootSequence,
const FSharedPlaybackStateCreateParams& CreateParams);
UE_API ~FSharedPlaybackState();
public:
/** Gets the playback context */
UObject* GetPlaybackContext() const { return WeakPlaybackContext.Get(); }
/** Gets the root sequence */
UMovieSceneSequence* GetRootSequence() const { return WeakRootSequence.Get(); }
/** Gets the linker evaluating this root sequence */
UMovieSceneEntitySystemLinker* GetLinker() const { return WeakLinker.Get(); }
/** Gets the compiled data manager that contains the data for the root sequence */
TObjectPtr<UMovieSceneCompiledDataManager> GetCompiledDataManager() const { return CompiledDataManager; }
/** Gets the handle of the root sequence */
const FRootInstanceHandle& GetRootInstanceHandle() const { return RootInstanceHandle; }
/** Gets the compiled data ID for the root sequence */
const FMovieSceneCompiledDataID& GetRootCompiledDataID() const { return RootCompiledDataID; }
/** Gets the pre-animated state utility for the sequence hierarchy */
const FMovieSceneInstancePreAnimatedState& GetPreAnimatedState() const { return PreAnimatedState; }
/** Gets the pre-animated state utility for the sequence hierarchy */
FMovieSceneInstancePreAnimatedState& GetPreAnimatedState() { return PreAnimatedState; }
public:
// General utility methods
/** Gets the runner evaluating this root sequence */
UE_API TSharedPtr<FMovieSceneEntitySystemRunner> GetRunner() const;
/** Gets the hierarchy (if any) for this root sequence */
UE_API const FMovieSceneSequenceHierarchy* GetHierarchy() const;
/** Gets a sub-sequence given an ID */
UE_API UMovieSceneSequence* GetSequence(FMovieSceneSequenceIDRef SequenceID) const;
/** Finds the bound objects for the given object binding in the given (sub)sequence */
UE_API TArrayView<TWeakObjectPtr<>> FindBoundObjects(const FGuid& ObjectBindingID, FMovieSceneSequenceIDRef SequenceID) const;
/** Clears object caches for the entire sequence hierarchy. */
UE_API void ClearObjectCaches();
public:
/**
* Gets the capabilities container.
*/
FPlaybackCapabilities& GetCapabilities()
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
return Capabilities;
}
/**
* Gets the capabilities container.
*/
const FPlaybackCapabilities& GetCapabilities() const
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
return Capabilities;
}
/**
* Returns whether the root sequence has the specified capability.
*/
template<typename T>
bool HasCapability() const
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
return Capabilities.HasCapability<T>();
}
/**
* Finds the specified capability on the root sequence.
*/
template<typename T>
T* FindCapability() const
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
return Capabilities.FindCapability<T>();
}
/**
* Builds the specified capability for the root sequence.
*/
template<typename T, typename ...ArgTypes>
T& AddCapability(ArgTypes&&... InArgs)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
T& Cap = Capabilities.AddCapability<T>(Forward<ArgTypes>(InArgs)...);
MaybeInitialize(Cap);
return Cap;
}
/**
* Adds the specified capability on the root sequence as a raw pointer.
*/
template<typename T>
T& AddCapabilityRaw(T* InPointer)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
T& Cap = Capabilities.AddCapabilityRaw<T>(InPointer);
MaybeInitialize(Cap);
return Cap;
}
/**
* Adds the specified capability on the root sequence as a shared pointer.
*/
template<typename T>
T& AddCapabilityShared(TSharedRef<T> InSharedRef)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
T& Cap = Capabilities.AddCapabilityShared<T>(InSharedRef);
MaybeInitialize(Cap);
return Cap;
}
/**
* Adds the specified capability on the root sequence.
* If the capability already exists, it must be stored inline, and its
* value will be replaced by the new object.
* If the template parameter is a sub-class of the playback capability, the previously
* stored playback capability must not only have been stored inline, but must have
* been of the same sub-class (or a sub-class with the exact same size and alignment).
*/
template<typename T, typename ...ArgTypes>
T& SetOrAddCapability(ArgTypes&&... InArgs)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
if (HasCapability<T>())
{
T& Cap = Capabilities.OverwriteCapability<T>(Forward<ArgTypes>(InArgs)...);
MaybeInitialize(Cap);
return Cap;
}
else
{
T& Cap = Capabilities.AddCapability<T>(Forward<ArgTypes>(InArgs)...);
MaybeInitialize(Cap);
return Cap;
}
}
/**
* Adds the specified capability on the root sequence as a raw pointer.
* If the capability already exists, it must be stored as a raw pointer and its
* value will be replaced by the new pointer.
*/
template<typename T, typename ...ArgTypes>
T& SetOrAddCapabilityRaw(T* InPointer)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
if (HasCapability<T>())
{
T& Cap = Capabilities.OverwriteCapabilityRaw<T>(InPointer);
MaybeInitialize(Cap);
return Cap;
}
else
{
T& Cap = Capabilities.AddCapabilityRaw<T>(InPointer);
MaybeInitialize(Cap);
return Cap;
}
}
/**
* Adds the specified capability on the root sequence as a shared pointer.
* If the capability already exists, it must be stored as a shared pointer and its
* value will be replaced by the new pointer.
*/
template<typename T, typename ...ArgTypes>
T& SetOrAddCapabilityShared(TSharedRef<T> InSharedRef)
{
#if !UE_BUILD_SHIPPING
ensureMsgf(IsInGameThread(),
TEXT("Playback capabilities aren't meant to be thread-safe. Do not modify or access their container outside of the game thread."));
#endif
if (HasCapability<T>())
{
T& Cap = Capabilities.OverwriteCapabilityShared<T>(InSharedRef);
MaybeInitialize(Cap);
return Cap;
}
else
{
T& Cap = Capabilities.AddCapabilityShared<T>(InSharedRef);
MaybeInitialize(Cap);
return Cap;
}
}
public:
UE_API void InvalidateCachedData();
#if !UE_BUILD_SHIPPING
void SetDebugBreakOnDestroy() { bDebugBreakOnDestroy = true; }
#endif
private:
template<typename T>
void MaybeInitialize(T& Cap)
{
if constexpr (TPointerIsConvertibleFromTo<T, IPlaybackCapability>::Value)
{
IPlaybackCapability* InterfacePtr = static_cast<IPlaybackCapability*>(&Cap);
InterfacePtr->Initialize(SharedThis(this));
}
}
private:
/** The root sequence */
TWeakObjectPtr<UMovieSceneSequence> WeakRootSequence;
/** The playback context */
TWeakObjectPtr<UObject> WeakPlaybackContext;
/** The linker evaluating this root sequence */
TWeakObjectPtr<UMovieSceneEntitySystemLinker> WeakLinker;
/** The compiled data manager that contains the data for the root sequence */
TObjectPtr<UMovieSceneCompiledDataManager> CompiledDataManager;
/** The handle of the root sequence */
FRootInstanceHandle RootInstanceHandle;
/** The compiled data ID for the root sequence */
FMovieSceneCompiledDataID RootCompiledDataID;
/** Playback capabilities for the root sequence */
FPlaybackCapabilities Capabilities;
/** Pre-animated state utility for the sequence hierarchy */
FMovieSceneInstancePreAnimatedState PreAnimatedState;
#if !UE_BUILD_SHIPPING
bool bDebugBreakOnDestroy = false;
#endif
};
} // namespace UE::MovieScene
#undef UE_API