Files
UnrealEngineUWP/Engine/Source/Runtime/MovieScene/Private/EntitySystem/MovieScenePreAnimatedStateSystem.cpp
max chen a20dc348ee Sequencer: Pre-Animated state changes to support track instance inputs
- Track Instance Inputs can now be used as capture sources to capture pre-animated state
  - PreAnimatedState extension now simply exists as a member of UMovieSceneEntitySystem. Previously the existence of the extension was used to determine whether any pre-animated state logic was required, but in practice this created more problems than it solved and led to some convoluted lifetime management code.
  - Added a templated group manager type from which the object group manager can inherit. This simplifies the introduction of new group managers
  - Removed the requirement that all pre-animated state must exist as part of a valid group. This forced state from 'master' tracks to be arbitrarily grouped together which put an unnecessary burden on the storage classes.

#jira UE-132512
#rb max.chen, matt.hoffman
[FYI] andrew.rodham
#preflight 61f2ca893765218cf01f290e

#ROBOMERGE-AUTHOR: max.chen
#ROBOMERGE-SOURCE: CL 18754810 in //UE5/Release-5.0/... via CL 18754825 via CL 18757520
#ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v903-18687472)

[CL 18758489 by max chen in ue5-main branch]
2022-01-27 14:35:51 -05:00

142 lines
5.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "EntitySystem/MovieScenePreAnimatedStateSystem.h"
#include "EntitySystem/MovieSceneEntitySystemLinker.h"
#include "EntitySystem/BuiltInComponentTypes.h"
#include "EntitySystem/MovieSceneEntitySystemTask.h"
#include "IMovieScenePlayer.h"
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedStateExtension.h"
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedStateStorage.h"
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedEntityCaptureSource.h"
UMovieSceneCachePreAnimatedStateSystem::UMovieSceneCachePreAnimatedStateSystem(const FObjectInitializer& ObjInit)
: Super(ObjInit)
{
using namespace UE::MovieScene;
if (HasAnyFlags(RF_ClassDefaultObject))
{
// This system relies upon anything that creates entities
DefineComponentConsumer(GetClass(), FBuiltInComponentTypes::Get()->SymbolicTags.CreatesEntities);
}
}
bool UMovieSceneCachePreAnimatedStateSystem::IsRelevantImpl(UMovieSceneEntitySystemLinker* InLinker) const
{
using namespace UE::MovieScene;
// This function can be called on the CDO and instances, so care is taken to do the right thing
const bool bHasRestoreStateEntities = InLinker->EntityManager.ContainsComponent(FBuiltInComponentTypes::Get()->Tags.RestoreState);
const bool bIsCapturingGlobalState = InLinker->PreAnimatedState.IsCapturingGlobalState();
return bHasRestoreStateEntities || bIsCapturingGlobalState;
}
void UMovieSceneCachePreAnimatedStateSystem::OnLink()
{
}
void UMovieSceneCachePreAnimatedStateSystem::OnUnlink()
{
}
void UMovieSceneCachePreAnimatedStateSystem::OnRun(FSystemTaskPrerequisites& InPrerequisites, FSystemSubsequentTasks& Subsequents)
{
using namespace UE::MovieScene;
TArray<IMovieScenePreAnimatedStateSystemInterface*, TInlineAllocator<16>> Interfaces;
auto ForEachSystem = [&Interfaces](UMovieSceneEntitySystem* InSystem)
{
if (IMovieScenePreAnimatedStateSystemInterface* PreAnimInterface = Cast<IMovieScenePreAnimatedStateSystemInterface>(InSystem))
{
Interfaces.Add(PreAnimInterface);
}
};
Linker->SystemGraph.IteratePhase(ESystemPhase::Spawn, ForEachSystem);
Linker->SystemGraph.IteratePhase(ESystemPhase::Instantiation, ForEachSystem);
Linker->SystemGraph.IteratePhase(ESystemPhase::Evaluation, ForEachSystem);
IMovieScenePreAnimatedStateSystemInterface::FPreAnimationParameters Params{ &InPrerequisites, &Subsequents, &Linker->PreAnimatedState };
for (IMovieScenePreAnimatedStateSystemInterface* Interface : Interfaces)
{
Interface->SavePreAnimatedState(Params);
}
}
UMovieSceneRestorePreAnimatedStateSystem::UMovieSceneRestorePreAnimatedStateSystem(const FObjectInitializer& ObjInit)
: Super(ObjInit)
{
using namespace UE::MovieScene;
if (HasAnyFlags(RF_ClassDefaultObject))
{
// This system relies upon anything that creates entities
DefineImplicitPrerequisite(UMovieSceneCachePreAnimatedStateSystem::StaticClass(), GetClass());
}
}
bool UMovieSceneRestorePreAnimatedStateSystem::IsRelevantImpl(UMovieSceneEntitySystemLinker* InLinker) const
{
using namespace UE::MovieScene;
return InLinker->EntityManager.ContainsComponent(FBuiltInComponentTypes::Get()->Tags.RestoreState);
}
void UMovieSceneRestorePreAnimatedStateSystem::OnLink()
{
using namespace UE::MovieScene;
UMovieSceneCachePreAnimatedStateSystem* CacheSystem = Linker->LinkSystem<UMovieSceneCachePreAnimatedStateSystem>();
Linker->SystemGraph.AddReference(this, CacheSystem);
}
void UMovieSceneRestorePreAnimatedStateSystem::OnUnlink()
{
}
void UMovieSceneRestorePreAnimatedStateSystem::OnRun(FSystemTaskPrerequisites& InPrerequisites, FSystemSubsequentTasks& Subsequents)
{
using namespace UE::MovieScene;
TArray<IMovieScenePreAnimatedStateSystemInterface*, TInlineAllocator<16>> Interfaces;
auto ForEachSystem = [&Interfaces](UMovieSceneEntitySystem* InSystem)
{
IMovieScenePreAnimatedStateSystemInterface* PreAnimInterface = Cast<IMovieScenePreAnimatedStateSystemInterface>(InSystem);
if (PreAnimInterface)
{
Interfaces.Add(PreAnimInterface);
}
};
Linker->SystemGraph.IteratePhase(ESystemPhase::Spawn, ForEachSystem);
Linker->SystemGraph.IteratePhase(ESystemPhase::Instantiation, ForEachSystem);
Linker->SystemGraph.IteratePhase(ESystemPhase::Evaluation, ForEachSystem);
IMovieScenePreAnimatedStateSystemInterface::FPreAnimationParameters Params{ &InPrerequisites, &Subsequents, &Linker->PreAnimatedState };
// Iterate backwards restoring stale state
for (int32 Index = Interfaces.Num()-1; Index >= 0; --Index)
{
Interfaces[Index]->RestorePreAnimatedState(Params);
}
FPreAnimatedEntityCaptureSource* EntityMetaData = Linker->PreAnimatedState.GetEntityMetaData();
if (EntityMetaData)
{
auto CleanupExpiredObjects = [EntityMetaData](FMovieSceneEntityID EntityID)
{
EntityMetaData->StopTrackingEntity(EntityID);
};
FEntityTaskBuilder()
.ReadEntityIDs()
.FilterAll({ FBuiltInComponentTypes::Get()->Tags.NeedsUnlink })
.Iterate_PerEntity(&Linker->EntityManager, CleanupExpiredObjects);
}
Params.CacheExtension->ResetEntryInvalidation();
}