2021-06-16 10:42:51 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "Systems/MovieSceneDataLayerSystem.h"
|
|
|
|
|
#include "EntitySystem/MovieSceneEntitySystemTask.h"
|
|
|
|
|
#include "EntitySystem/MovieSceneSpawnablesSystem.h"
|
|
|
|
|
#include "EntitySystem/MovieSceneEntitySystemLinker.h"
|
|
|
|
|
#include "EntitySystem/BuiltInComponentTypes.h"
|
|
|
|
|
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedEntityCaptureSource.h"
|
|
|
|
|
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedStateStorage.h"
|
|
|
|
|
#include "Evaluation/PreAnimatedState/MovieScenePreAnimatedStorageID.inl"
|
2021-12-02 23:53:01 -05:00
|
|
|
#include "Evaluation/MovieSceneEvaluationTemplateInstance.h"
|
2021-06-16 10:42:51 -04:00
|
|
|
#include "MovieSceneTracksComponentTypes.h"
|
2021-12-05 17:40:05 -05:00
|
|
|
#include "ProfilingDebugging/CsvProfiler.h"
|
2021-06-16 10:42:51 -04:00
|
|
|
#include "Sections/MovieSceneDataLayerSection.h"
|
|
|
|
|
#include "WorldPartition/DataLayer/DataLayerSubsystem.h"
|
2022-03-15 13:52:28 -04:00
|
|
|
#include "WorldPartition/DataLayer/DataLayerInstance.h"
|
2021-07-29 14:53:00 -04:00
|
|
|
#include "WorldPartition/WorldPartitionSubsystem.h"
|
|
|
|
|
#include "WorldPartition/WorldPartitionRuntimeCell.h"
|
|
|
|
|
#include "WorldPartition/WorldPartitionStreamingSource.h"
|
2021-06-16 10:42:51 -04:00
|
|
|
#include "Engine/World.h"
|
2021-06-24 15:33:05 -04:00
|
|
|
#include "Misc/EnumClassFlags.h"
|
2021-12-02 23:53:01 -05:00
|
|
|
#include "MovieSceneSequence.h"
|
|
|
|
|
#include "IMovieScenePlayer.h"
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
#include "Kismet/KismetSystemLibrary.h"
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
#include "DataLayer/DataLayerEditorSubsystem.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace UE
|
|
|
|
|
{
|
|
|
|
|
namespace MovieScene
|
|
|
|
|
{
|
|
|
|
|
|
2021-06-24 15:33:05 -04:00
|
|
|
enum class EDataLayerUpdateFlags : uint8
|
|
|
|
|
{
|
2021-08-07 15:20:22 -04:00
|
|
|
None = 0,
|
|
|
|
|
FlushStreamingVisibility = 1,
|
|
|
|
|
FlushStreamingFull = 2,
|
2021-06-24 15:33:05 -04:00
|
|
|
};
|
|
|
|
|
ENUM_CLASS_FLAGS(EDataLayerUpdateFlags)
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
/** Traits class governing how pre-animated state is (re)stored for data layers */
|
|
|
|
|
struct FPreAnimatedDataLayerStorageTraits
|
|
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
using KeyType = TObjectKey<UDataLayerInstance>;
|
2021-11-07 23:43:01 -05:00
|
|
|
using StorageType = EDataLayerRuntimeState;
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
/** Called when a previously animated data layer needs to be restored */
|
2022-03-15 13:52:28 -04:00
|
|
|
static void RestorePreAnimatedValue(const TObjectKey<UDataLayerInstance>& InKey, EDataLayerRuntimeState PreviousState, const FRestoreStateParams& Params);
|
2021-06-16 10:42:51 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Container class for all pre-animated data layer state */
|
|
|
|
|
struct FPreAnimatedDataLayerStorage
|
|
|
|
|
: TPreAnimatedStateStorage<FPreAnimatedDataLayerStorageTraits>
|
|
|
|
|
, IPreAnimatedStateGroupManager
|
|
|
|
|
{
|
|
|
|
|
static TAutoRegisterPreAnimatedStorageID<FPreAnimatedDataLayerStorage> StorageID;
|
|
|
|
|
static TAutoRegisterPreAnimatedStorageID<FPreAnimatedDataLayerStorage> GroupManagerID;
|
|
|
|
|
|
|
|
|
|
/*~ IPreAnimatedStateGroupManager */
|
|
|
|
|
void InitializeGroupManager(FPreAnimatedStateExtension* Extension) override;
|
|
|
|
|
void OnGroupDestroyed(FPreAnimatedStorageGroupHandle Group) override;
|
|
|
|
|
|
|
|
|
|
/** Make an entry for the specified data layer */
|
2022-03-15 13:52:28 -04:00
|
|
|
FPreAnimatedStateEntry MakeEntry(UDataLayerInstance* InDataLayer);
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
/** Save the value of a data layer. Should only be used for runtime / PIE worlds */
|
2022-03-15 13:52:28 -04:00
|
|
|
void SavePreAnimatedState(UDataLayerInstance* DataLayer, UDataLayerSubsystem* SubSystem);
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
/** Save the value of a data layer. Should only be used for editor worlds */
|
2022-03-15 13:52:28 -04:00
|
|
|
void SavePreAnimatedStateInEditor(UDataLayerInstance* DataLayer);
|
2021-06-16 10:42:51 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
FPreAnimatedStorageGroupHandle GroupHandle;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct FDataLayerState
|
|
|
|
|
{
|
|
|
|
|
void Reset();
|
|
|
|
|
bool IsEmpty() const;
|
2021-11-07 23:43:01 -05:00
|
|
|
void AddRequest(int16 InBias, EDataLayerRuntimeState RequestedState, bool bRequiresStreamingFlush);
|
|
|
|
|
TOptional<EDataLayerRuntimeState> ComputeDesiredState() const;
|
|
|
|
|
bool ShouldFlushStreaming(EDataLayerRuntimeState ComputedState) const;
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
int16 HierarchicalBias = 0;
|
|
|
|
|
int32 UnloadedCount = 0;
|
|
|
|
|
int32 LoadedCount = 0;
|
|
|
|
|
int32 ActivatedCount = 0;
|
2021-07-29 12:53:55 -04:00
|
|
|
bool bFlushUnloaded = false;
|
|
|
|
|
bool bFlushActivated = false;
|
2021-06-16 10:42:51 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct FDesiredLayerStates
|
|
|
|
|
{
|
|
|
|
|
bool IsEmpty() const;
|
|
|
|
|
void Reset();
|
2021-07-29 14:53:00 -04:00
|
|
|
EDataLayerUpdateFlags Apply(FPreAnimatedDataLayerStorage* PreAnimatedStorage, UDataLayerSubsystem* DataLayerSubsystem, UWorldPartitionSubsystem* WorldPartitionSubsystem);
|
2021-06-16 10:42:51 -04:00
|
|
|
#if WITH_EDITOR
|
|
|
|
|
void ApplyInEditor(FPreAnimatedDataLayerStorage* PreAnimatedStorage, UDataLayerEditorSubsystem* EditorSubSystem);
|
|
|
|
|
#endif
|
2021-11-07 23:43:01 -05:00
|
|
|
void ApplyNewState(const FName& InDataLayerName, int16 HierarchicalBias, EDataLayerRuntimeState DesiredState, bool bRequiresStreamingFlush);
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
TMap<FName, FDataLayerState> StatesByLayer;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
|
// FPreAnimatedDataLayerStorageTraits definitions
|
2022-03-15 13:52:28 -04:00
|
|
|
void FPreAnimatedDataLayerStorageTraits::RestorePreAnimatedValue(const TObjectKey<UDataLayerInstance>& InKey, EDataLayerRuntimeState PreviousState, const FRestoreStateParams& Params)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
UDataLayerInstance* DataLayer = InKey.ResolveObjectPtr();
|
2021-06-16 10:42:51 -04:00
|
|
|
if (!DataLayer)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UWorld* World = DataLayer->GetWorld();
|
|
|
|
|
if (World)
|
|
|
|
|
{
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
if (World->WorldType == EWorldType::Editor)
|
|
|
|
|
{
|
|
|
|
|
UDataLayerEditorSubsystem* SubSystem = UDataLayerEditorSubsystem::Get();
|
2021-11-07 23:43:01 -05:00
|
|
|
SubSystem->SetDataLayerVisibility(DataLayer, PreviousState == EDataLayerRuntimeState::Activated);
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if (UDataLayerSubsystem* SubSystem = World->GetSubsystem<UDataLayerSubsystem>())
|
|
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
SubSystem->SetDataLayerRuntimeState(DataLayer, PreviousState);
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
|
// FPreAnimatedDataLayerStorage definitions
|
|
|
|
|
TAutoRegisterPreAnimatedStorageID<FPreAnimatedDataLayerStorage> FPreAnimatedDataLayerStorage::StorageID;
|
|
|
|
|
TAutoRegisterPreAnimatedStorageID<FPreAnimatedDataLayerStorage> FPreAnimatedDataLayerStorage::GroupManagerID;
|
|
|
|
|
|
|
|
|
|
void FPreAnimatedDataLayerStorage::InitializeGroupManager(FPreAnimatedStateExtension* Extension)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void FPreAnimatedDataLayerStorage::OnGroupDestroyed(FPreAnimatedStorageGroupHandle Group)
|
|
|
|
|
{
|
|
|
|
|
ensure(Group == GroupHandle);
|
|
|
|
|
GroupHandle = FPreAnimatedStorageGroupHandle();
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 13:52:28 -04:00
|
|
|
FPreAnimatedStateEntry FPreAnimatedDataLayerStorage::MakeEntry(UDataLayerInstance* InDataLayer)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
if (!GroupHandle)
|
|
|
|
|
{
|
|
|
|
|
GroupHandle = ParentExtension->AllocateGroup(SharedThis(this));
|
|
|
|
|
}
|
|
|
|
|
FPreAnimatedStorageIndex StorageIndex = GetOrCreateStorageIndex(InDataLayer);
|
|
|
|
|
return FPreAnimatedStateEntry{ GroupHandle, FPreAnimatedStateCachedValueHandle{ StorageID, StorageIndex } };
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 13:52:28 -04:00
|
|
|
void FPreAnimatedDataLayerStorage::SavePreAnimatedState(UDataLayerInstance* DataLayer, UDataLayerSubsystem* SubSystem)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
FPreAnimatedStateEntry Entry = MakeEntry(DataLayer);
|
|
|
|
|
EPreAnimatedStorageRequirement StorageRequirement = this->ParentExtension->GetStorageRequirement(Entry);
|
|
|
|
|
|
|
|
|
|
if (!IsStorageRequirementSatisfied(Entry.ValueHandle.StorageIndex, StorageRequirement))
|
|
|
|
|
{
|
|
|
|
|
// @todo: If a data layer is loading when Sequencer attempts to activate it,
|
|
|
|
|
// should it return to ::Loading when sequencer is done?
|
2021-11-07 23:43:01 -05:00
|
|
|
EDataLayerRuntimeState ExistingState = SubSystem->GetDataLayerRuntimeState(DataLayer);
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
AssignPreAnimatedValue(Entry.ValueHandle.StorageIndex, StorageRequirement, CopyTemp(ExistingState));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
2022-03-15 13:52:28 -04:00
|
|
|
void FPreAnimatedDataLayerStorage::SavePreAnimatedStateInEditor(UDataLayerInstance* DataLayer)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
FPreAnimatedStateEntry Entry = MakeEntry(DataLayer);
|
|
|
|
|
EPreAnimatedStorageRequirement StorageRequirement = this->ParentExtension->GetStorageRequirement(Entry);
|
|
|
|
|
|
|
|
|
|
if (!IsStorageRequirementSatisfied(Entry.ValueHandle.StorageIndex, StorageRequirement))
|
|
|
|
|
{
|
|
|
|
|
// We never unload data-layers in editor, so feign currently unloaded layers as loaded
|
2021-11-07 23:43:01 -05:00
|
|
|
EDataLayerRuntimeState ExistingState = (DataLayer->IsVisible() && DataLayer->IsLoadedInEditor()) ? EDataLayerRuntimeState::Activated : EDataLayerRuntimeState::Loaded;
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
AssignPreAnimatedValue(Entry.ValueHandle.StorageIndex, StorageRequirement, CopyTemp(ExistingState));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
|
// FDataLayerState definitions
|
|
|
|
|
void FDataLayerState::Reset()
|
|
|
|
|
{
|
|
|
|
|
HierarchicalBias = 0;
|
|
|
|
|
UnloadedCount = 0;
|
|
|
|
|
LoadedCount = 0;
|
|
|
|
|
ActivatedCount = 0;
|
2021-07-29 12:53:55 -04:00
|
|
|
bFlushUnloaded = false;
|
|
|
|
|
bFlushActivated = false;
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
void FDataLayerState::AddRequest(int16 InBias, EDataLayerRuntimeState RequestedState, bool bRequiresStreamingFlush)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
if (InBias > HierarchicalBias)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
HierarchicalBias = InBias;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (InBias == HierarchicalBias)
|
|
|
|
|
{
|
|
|
|
|
switch (RequestedState)
|
|
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Unloaded: ++UnloadedCount; bFlushUnloaded |= bRequiresStreamingFlush; break;
|
|
|
|
|
case EDataLayerRuntimeState::Loaded: ++LoadedCount; break;
|
|
|
|
|
case EDataLayerRuntimeState::Activated: ++ActivatedCount; bFlushActivated |= bRequiresStreamingFlush; break;
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FDataLayerState::IsEmpty() const
|
|
|
|
|
{
|
|
|
|
|
return (UnloadedCount + LoadedCount + ActivatedCount) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
TOptional<EDataLayerRuntimeState> FDataLayerState::ComputeDesiredState() const
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2021-12-02 23:58:50 -05:00
|
|
|
if (ActivatedCount > 0)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
return EDataLayerRuntimeState::Activated;
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
2021-12-02 23:58:50 -05:00
|
|
|
else if (LoadedCount > 0)
|
|
|
|
|
{
|
|
|
|
|
return EDataLayerRuntimeState::Loaded;
|
|
|
|
|
}
|
|
|
|
|
else if (UnloadedCount > 0)
|
|
|
|
|
{
|
|
|
|
|
return EDataLayerRuntimeState::Unloaded;
|
|
|
|
|
}
|
2021-06-16 10:42:51 -04:00
|
|
|
|
2021-12-02 23:58:50 -05:00
|
|
|
return TOptional<EDataLayerRuntimeState>();
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
bool FDataLayerState::ShouldFlushStreaming(EDataLayerRuntimeState ComputedState) const
|
2021-07-29 12:53:55 -04:00
|
|
|
{
|
|
|
|
|
switch (ComputedState)
|
|
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Unloaded: return bFlushUnloaded;
|
|
|
|
|
case EDataLayerRuntimeState::Activated: return bFlushActivated;
|
2021-07-29 12:53:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
|
// FDataLayerStates definitions
|
|
|
|
|
bool FDesiredLayerStates::IsEmpty() const
|
|
|
|
|
{
|
|
|
|
|
return StatesByLayer.Num() == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FDesiredLayerStates::Reset()
|
|
|
|
|
{
|
|
|
|
|
for (TTuple<FName, FDataLayerState>& Pair : StatesByLayer)
|
|
|
|
|
{
|
|
|
|
|
Pair.Value.Reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 14:53:00 -04:00
|
|
|
EDataLayerUpdateFlags FDesiredLayerStates::Apply(FPreAnimatedDataLayerStorage* PreAnimatedStorage, UDataLayerSubsystem* DataLayerSubsystem, UWorldPartitionSubsystem* WorldPartitionSubsystem)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2021-06-24 15:33:05 -04:00
|
|
|
EDataLayerUpdateFlags Flags = EDataLayerUpdateFlags::None;
|
|
|
|
|
|
2022-03-15 13:52:28 -04:00
|
|
|
auto IsDataLayerReady = [WorldPartitionSubsystem](UDataLayerInstance* DataLayer, EDataLayerRuntimeState DesireState, bool bExactState)
|
2021-07-29 14:53:00 -04:00
|
|
|
{
|
|
|
|
|
EWorldPartitionRuntimeCellState QueryState;
|
|
|
|
|
switch (DesireState)
|
|
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Activated:
|
2021-07-29 14:53:00 -04:00
|
|
|
QueryState = EWorldPartitionRuntimeCellState::Activated;
|
|
|
|
|
break;
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Loaded:
|
2021-07-29 14:53:00 -04:00
|
|
|
QueryState = EWorldPartitionRuntimeCellState::Loaded;
|
|
|
|
|
break;
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Unloaded:
|
2021-07-29 14:53:00 -04:00
|
|
|
QueryState = EWorldPartitionRuntimeCellState::Unloaded;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
UE_LOG(LogMovieScene, Error, TEXT("Unkown data layer state"));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FWorldPartitionStreamingQuerySource QuerySource;
|
|
|
|
|
QuerySource.bDataLayersOnly = true;
|
|
|
|
|
QuerySource.bSpatialQuery = false; // @todo_ow: how would we support spatial query from sequencer?
|
2022-03-15 13:52:28 -04:00
|
|
|
QuerySource.DataLayers.Add(DataLayer->GetDataLayerFName());
|
2021-08-07 15:20:22 -04:00
|
|
|
return WorldPartitionSubsystem->IsStreamingCompleted(QueryState, { QuerySource }, bExactState);
|
2021-07-29 14:53:00 -04:00
|
|
|
};
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
for (auto It = StatesByLayer.CreateIterator(); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
const FDataLayerState& StateValue = It.Value();
|
|
|
|
|
if (StateValue.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
It.RemoveCurrent();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
if (TOptional<EDataLayerRuntimeState> DesiredState = StateValue.ComputeDesiredState())
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
UDataLayerInstance* DataLayer = DataLayerSubsystem->GetDataLayerInstance(It.Key());
|
2021-06-16 10:42:51 -04:00
|
|
|
if (DataLayer)
|
|
|
|
|
{
|
|
|
|
|
if (PreAnimatedStorage)
|
|
|
|
|
{
|
2021-07-29 14:53:00 -04:00
|
|
|
PreAnimatedStorage->SavePreAnimatedState(DataLayer, DataLayerSubsystem);
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
const EDataLayerRuntimeState DesiredStateValue = DesiredState.GetValue();
|
|
|
|
|
DataLayerSubsystem->SetDataLayerRuntimeState(DataLayer, DesiredStateValue);
|
2021-06-24 15:33:05 -04:00
|
|
|
|
2021-08-07 15:20:22 -04:00
|
|
|
if (StateValue.ShouldFlushStreaming(DesiredStateValue) && !IsDataLayerReady(DataLayer, DesiredStateValue, true))
|
2021-06-24 15:33:05 -04:00
|
|
|
{
|
2021-08-07 15:20:22 -04:00
|
|
|
// Exception for Full flush is if Desired State is Activated but we are not at least in Loaded state
|
2021-11-07 23:43:01 -05:00
|
|
|
if (DesiredStateValue == EDataLayerRuntimeState::Activated && !IsDataLayerReady(DataLayer, EDataLayerRuntimeState::Loaded, false))
|
2021-08-07 15:20:22 -04:00
|
|
|
{
|
|
|
|
|
Flags |= EDataLayerUpdateFlags::FlushStreamingFull;
|
2021-12-03 14:24:33 -05:00
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("[UMovieSceneDataLayerSystem] Data layer with name '%s' is causing a full streaming flush (%s)"),
|
2022-03-15 13:52:28 -04:00
|
|
|
*DataLayer->GetDataLayerShortName(),
|
2021-12-03 14:24:33 -05:00
|
|
|
*StaticEnum<EDataLayerRuntimeState>()->GetDisplayNameTextByValue((int64)DesiredStateValue).ToString());
|
|
|
|
|
|
|
|
|
|
CSV_EVENT_GLOBAL(TEXT("SeqDataLayerFlushFull-%s-%s"),
|
2022-03-15 13:52:28 -04:00
|
|
|
*DataLayer->GetDataLayerShortName(),
|
2021-12-03 14:35:05 -05:00
|
|
|
*StaticEnum<EDataLayerRuntimeState>()->GetDisplayNameTextByValue((int64)DesiredStateValue).ToString());
|
2021-08-07 15:20:22 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Flags |= EDataLayerUpdateFlags::FlushStreamingVisibility;
|
2021-12-03 14:24:33 -05:00
|
|
|
UE_LOG(LogMovieScene, Log, TEXT("[UMovieSceneDataLayerSystem] Data layer with name '%s' is causing a visibility streaming flush (%s)"),
|
2022-03-15 13:52:28 -04:00
|
|
|
*DataLayer->GetDataLayerShortName(),
|
2021-12-03 14:24:33 -05:00
|
|
|
*StaticEnum<EDataLayerRuntimeState>()->GetDisplayNameTextByValue((int64)DesiredStateValue).ToString());
|
|
|
|
|
|
|
|
|
|
CSV_EVENT_GLOBAL(TEXT("SeqDataLayerFlushVis-%s-%s"),
|
2022-03-15 13:52:28 -04:00
|
|
|
*DataLayer->GetDataLayerShortName(),
|
2021-12-03 14:24:33 -05:00
|
|
|
*StaticEnum<EDataLayerRuntimeState>()->GetDisplayNameTextByValue((int64)DesiredStateValue).ToString());
|
2021-08-07 15:20:22 -04:00
|
|
|
}
|
2021-06-24 15:33:05 -04:00
|
|
|
}
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("Unable to find data layer with name '%s'"), *It.Key().ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-24 15:33:05 -04:00
|
|
|
|
|
|
|
|
return Flags;
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
void FDesiredLayerStates::ApplyInEditor(FPreAnimatedDataLayerStorage* PreAnimatedStorage, UDataLayerEditorSubsystem* SubSystem)
|
|
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
TArray<UDataLayerInstance*> DatalayersNeedingLoad;
|
|
|
|
|
TArray<UDataLayerInstance*> DatalayersNeedingShow;
|
|
|
|
|
TArray<UDataLayerInstance*> DatalayersNeedingHide;
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
for (auto It = StatesByLayer.CreateIterator(); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
const FDataLayerState& StateValue = It.Value();
|
|
|
|
|
if (StateValue.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
It.RemoveCurrent();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
if (TOptional<EDataLayerRuntimeState> DesiredState = StateValue.ComputeDesiredState())
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
UDataLayerInstance* DataLayer = SubSystem->GetDataLayerInstance(It.Key());
|
2021-06-16 10:42:51 -04:00
|
|
|
if (DataLayer)
|
|
|
|
|
{
|
|
|
|
|
if (PreAnimatedStorage)
|
|
|
|
|
{
|
|
|
|
|
PreAnimatedStorage->SavePreAnimatedStateInEditor(DataLayer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// In-editor we only ever hide data layers, we never unload them
|
|
|
|
|
switch (DesiredState.GetValue())
|
|
|
|
|
{
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Unloaded:
|
2021-06-16 10:42:51 -04:00
|
|
|
DatalayersNeedingHide.Add(DataLayer);
|
|
|
|
|
break;
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Loaded:
|
2021-06-16 10:42:51 -04:00
|
|
|
DatalayersNeedingLoad.Add(DataLayer);
|
|
|
|
|
DatalayersNeedingHide.Add(DataLayer);
|
|
|
|
|
break;
|
2021-11-07 23:43:01 -05:00
|
|
|
case EDataLayerRuntimeState::Activated:
|
2021-06-16 10:42:51 -04:00
|
|
|
DatalayersNeedingLoad.Add(DataLayer);
|
|
|
|
|
DatalayersNeedingShow.Add(DataLayer);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("Unable to find data layer with name '%s'"), *It.Key().ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DatalayersNeedingLoad.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
// This blocks while we load data layers
|
2021-11-07 23:43:01 -05:00
|
|
|
SubSystem->SetDataLayersIsLoadedInEditor(DatalayersNeedingLoad, true, /*bIsFromUserChange*/false);
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
if (DatalayersNeedingShow.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
SubSystem->SetDataLayersVisibility(DatalayersNeedingShow, true);
|
|
|
|
|
}
|
|
|
|
|
if (DatalayersNeedingHide.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
SubSystem->SetDataLayersVisibility(DatalayersNeedingHide, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
void FDesiredLayerStates::ApplyNewState(const FName& InDataLayerName, int16 HierarchicalBias, EDataLayerRuntimeState DesiredState, bool bRequiresStreamingFlush)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
using namespace UE::MovieScene;
|
|
|
|
|
|
|
|
|
|
FDataLayerState* LayerState = StatesByLayer.Find(InDataLayerName);
|
|
|
|
|
if (!LayerState)
|
|
|
|
|
{
|
|
|
|
|
LayerState = &StatesByLayer.Add(InDataLayerName, FDataLayerState());
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 12:53:55 -04:00
|
|
|
LayerState->AddRequest(HierarchicalBias, DesiredState, bRequiresStreamingFlush);
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace MovieScene
|
|
|
|
|
} // namespace UE
|
|
|
|
|
|
|
|
|
|
UMovieSceneDataLayerSystem::UMovieSceneDataLayerSystem(const FObjectInitializer& ObjInit)
|
|
|
|
|
: Super(ObjInit)
|
|
|
|
|
{
|
|
|
|
|
using namespace UE::MovieScene;
|
|
|
|
|
|
|
|
|
|
FBuiltInComponentTypes* BuiltInComponents = FBuiltInComponentTypes::Get();
|
|
|
|
|
FMovieSceneTracksComponentTypes* TracksComponents = FMovieSceneTracksComponentTypes::Get();
|
|
|
|
|
|
|
|
|
|
Phase = UE::MovieScene::ESystemPhase::Spawn;
|
|
|
|
|
RelevantComponent = TracksComponents->DataLayer;
|
|
|
|
|
|
|
|
|
|
if (HasAnyFlags(RF_ClassDefaultObject))
|
|
|
|
|
{
|
|
|
|
|
DefineImplicitPrerequisite(GetClass(), UMovieSceneSpawnablesSystem::StaticClass());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DesiredLayerStates = MakeShared<FDesiredLayerStates>();
|
|
|
|
|
|
|
|
|
|
// We only need to run if there are data layer components that need (un)linking
|
|
|
|
|
ApplicableFilter.Filter.All({ TracksComponents->DataLayer });
|
|
|
|
|
ApplicableFilter.Filter.Any({ BuiltInComponents->Tags.NeedsLink, BuiltInComponents->Tags.NeedsUnlink });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMovieSceneDataLayerSystem::OnLink()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UMovieSceneDataLayerSystem::IsRelevantImpl(UMovieSceneEntitySystemLinker* InLinker) const
|
|
|
|
|
{
|
|
|
|
|
return InLinker->EntityManager.ContainsComponent(RelevantComponent) || (DesiredLayerStates && !DesiredLayerStates->IsEmpty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMovieSceneDataLayerSystem::OnRun(FSystemTaskPrerequisites& InPrerequisites, FSystemSubsequentTasks& Subsequents)
|
|
|
|
|
{
|
2021-06-24 15:33:05 -04:00
|
|
|
using namespace UE::MovieScene;
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
// Only run if we must
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
|
|
|
|
|
if (!World || !ApplicableFilter.Matches(Linker->EntityManager))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the desired states of all data layers from the entity manager
|
|
|
|
|
UpdateDesiredStates();
|
|
|
|
|
|
|
|
|
|
// In-editor we apply desired states through the editor sub-system
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
if (World->WorldType == EWorldType::Editor)
|
|
|
|
|
{
|
|
|
|
|
UDataLayerEditorSubsystem* DataLayerEditorSubsystem = UDataLayerEditorSubsystem::Get();
|
2021-08-10 19:26:27 -04:00
|
|
|
if (!DataLayerEditorSubsystem)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("Unable to retrieve data layer editor subsystem - data layer tracks will not function correctly"));
|
|
|
|
|
}
|
|
|
|
|
else
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
DesiredLayerStates->ApplyInEditor(WeakPreAnimatedStorage.Pin().Get(), DataLayerEditorSubsystem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Outside of editor, or in PIE, we use the runtime data layer sub-system
|
|
|
|
|
{
|
2021-07-29 14:53:00 -04:00
|
|
|
UWorldPartitionSubsystem* WorldPartitionSubsystem = World->GetSubsystem<UWorldPartitionSubsystem>();
|
2021-08-10 19:26:27 -04:00
|
|
|
if (!WorldPartitionSubsystem)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("Unable to retrieve world partition subsystem - data layer tracks will not function correctly"));
|
|
|
|
|
}
|
|
|
|
|
else
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2021-07-29 14:53:00 -04:00
|
|
|
UDataLayerSubsystem* DataLayerSubsystem = World->GetSubsystem<UDataLayerSubsystem>();
|
2021-08-10 19:26:27 -04:00
|
|
|
if (!DataLayerSubsystem)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("Unable to retrieve data layer subsystem - data layer tracks will not function correctly"));
|
|
|
|
|
}
|
|
|
|
|
else
|
2021-06-24 15:33:05 -04:00
|
|
|
{
|
2021-07-29 14:53:00 -04:00
|
|
|
EDataLayerUpdateFlags UpdateFlags = DesiredLayerStates->Apply(WeakPreAnimatedStorage.Pin().Get(), DataLayerSubsystem, WorldPartitionSubsystem);
|
|
|
|
|
|
2021-12-02 23:53:01 -05:00
|
|
|
const double StartTime = FPlatformTime::Seconds();
|
|
|
|
|
const TCHAR* FlushTypeString = nullptr;
|
|
|
|
|
|
2021-08-07 15:20:22 -04:00
|
|
|
if (EnumHasAnyFlags(UpdateFlags, EDataLayerUpdateFlags::FlushStreamingFull))
|
2021-07-29 14:53:00 -04:00
|
|
|
{
|
2021-12-02 20:49:45 -05:00
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(UMovieSceneDataLayerSystem_FlushStreamingFull);
|
2021-12-02 23:53:01 -05:00
|
|
|
FlushTypeString = TEXT("FlushStreamingFull");
|
|
|
|
|
|
2021-07-29 14:53:00 -04:00
|
|
|
World->BlockTillLevelStreamingCompleted();
|
|
|
|
|
}
|
2021-08-07 15:20:22 -04:00
|
|
|
else if (EnumHasAnyFlags(UpdateFlags, EDataLayerUpdateFlags::FlushStreamingVisibility))
|
|
|
|
|
{
|
2021-12-02 20:49:45 -05:00
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(UMovieSceneDataLayerSystem_FlushStreamingVisibility);
|
2021-12-02 23:53:01 -05:00
|
|
|
FlushTypeString = TEXT("FlushStreamingVisibility");
|
2021-12-02 20:49:45 -05:00
|
|
|
|
|
|
|
|
// Make sure any DataLayer state change is processed before flushing visibility
|
2021-08-07 15:20:22 -04:00
|
|
|
WorldPartitionSubsystem->UpdateStreamingState();
|
|
|
|
|
World->FlushLevelStreaming(EFlushLevelStreamingType::Visibility);
|
|
|
|
|
}
|
2021-12-02 23:53:01 -05:00
|
|
|
|
|
|
|
|
UE_SUPPRESS(LogMovieScene, Warning,
|
|
|
|
|
{
|
|
|
|
|
if (FlushTypeString)
|
|
|
|
|
{
|
|
|
|
|
FString SequenceList;
|
|
|
|
|
for (const FSequenceInstance& Instance : Linker->GetInstanceRegistry()->GetSparseInstances())
|
|
|
|
|
{
|
|
|
|
|
UMovieSceneSequence* Sequence = Instance.GetPlayer()->GetEvaluationTemplate().GetSequence(Instance.GetSequenceID());
|
|
|
|
|
|
|
|
|
|
if (SequenceList.Len())
|
|
|
|
|
{
|
|
|
|
|
SequenceList += TEXT(",");
|
|
|
|
|
}
|
|
|
|
|
SequenceList += Sequence->GetName();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogMovieScene, Warning, TEXT("[UMovieSceneDataLayerSystem] %s took %.4f seconds (%s)"), FlushTypeString, FPlatformTime::Seconds() - StartTime, *SequenceList);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-06-24 15:33:05 -04:00
|
|
|
}
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMovieSceneDataLayerSystem::UpdateDesiredStates()
|
|
|
|
|
{
|
|
|
|
|
using namespace UE::MovieScene;
|
|
|
|
|
|
|
|
|
|
FBuiltInComponentTypes* BuiltInComponents = FBuiltInComponentTypes::Get();
|
|
|
|
|
FMovieSceneTracksComponentTypes* TracksComponents = FMovieSceneTracksComponentTypes::Get();
|
|
|
|
|
|
|
|
|
|
BeginTrackingEntities();
|
|
|
|
|
|
|
|
|
|
// Reset the container and re-harvest all active states from the entity manager
|
|
|
|
|
DesiredLayerStates->Reset();
|
|
|
|
|
|
|
|
|
|
auto GatherDataLayers = [this, BuiltInComponents](FEntityAllocationIteratorItem Item, const FMovieSceneDataLayerComponentData* ComponentData, const int16* OptHBiases)
|
|
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
UDataLayerSubsystem* DataLayerSubsystem = World ? World->GetSubsystem<UDataLayerSubsystem>() : nullptr;
|
|
|
|
|
if (!DataLayerSubsystem)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
const bool bPreroll = Item.GetAllocationType().Contains(BuiltInComponents->Tags.PreRoll);
|
|
|
|
|
for (int32 Index = 0; Index < Item.GetAllocation()->Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
const UMovieSceneDataLayerSection* Section = ComponentData[Index].Section.Get();
|
|
|
|
|
if (!ensure(Section))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
EDataLayerRuntimeState DesiredState = bPreroll ? Section->GetPrerollState() : Section->GetDesiredState();
|
2021-12-03 14:24:33 -05:00
|
|
|
const bool bRequiresStreamingFlush = (DesiredState == EDataLayerRuntimeState::Unloaded) ? Section->GetFlushOnUnload() : !bPreroll;
|
2021-06-16 10:42:51 -04:00
|
|
|
|
2022-03-15 13:52:28 -04:00
|
|
|
for (const UDataLayerAsset* DataLayerAsset : Section->GetDataLayerAssets())
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-05-05 15:15:33 -04:00
|
|
|
const UDataLayerInstance* DataLayerInstance = DataLayerSubsystem->GetDataLayerInstanceFromAsset(DataLayerAsset);
|
2022-03-15 13:52:28 -04:00
|
|
|
if (DataLayerInstance)
|
|
|
|
|
{
|
|
|
|
|
this->DesiredLayerStates->ApplyNewState(DataLayerInstance->GetDataLayerFName(), OptHBiases ? OptHBiases[Index] : 0, DesiredState, bRequiresStreamingFlush);
|
|
|
|
|
}
|
2021-06-16 10:42:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
FEntityTaskBuilder()
|
|
|
|
|
.Read(TracksComponents->DataLayer)
|
|
|
|
|
.ReadOptional(BuiltInComponents->HierarchicalBias)
|
|
|
|
|
.FilterNone({ BuiltInComponents->Tags.NeedsUnlink }) // Do not iterate things that are being destroyed
|
|
|
|
|
.Iterate_PerAllocation(&Linker->EntityManager, GatherDataLayers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMovieSceneDataLayerSystem::BeginTrackingEntities()
|
|
|
|
|
{
|
|
|
|
|
using namespace UE::MovieScene;
|
|
|
|
|
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
UDataLayerSubsystem* DataLayerSubsystem = World ? World->GetSubsystem<UDataLayerSubsystem>() : nullptr;
|
|
|
|
|
|
2022-01-27 14:35:51 -05:00
|
|
|
if (!DataLayerSubsystem)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FBuiltInComponentTypes* BuiltInComponents = FBuiltInComponentTypes::Get();
|
|
|
|
|
FMovieSceneTracksComponentTypes* TracksComponents = FMovieSceneTracksComponentTypes::Get();
|
2022-01-27 14:35:51 -05:00
|
|
|
FPreAnimatedEntityCaptureSource* EntityMetaData = Linker->PreAnimatedState.GetOrCreateEntityMetaData();
|
2021-06-16 10:42:51 -04:00
|
|
|
|
|
|
|
|
// Cache the preanimated storage
|
2022-01-27 14:35:51 -05:00
|
|
|
TSharedPtr<FPreAnimatedDataLayerStorage> PreAnimatedStorage = Linker->PreAnimatedState.GetOrCreateStorage<FPreAnimatedDataLayerStorage>();
|
2021-06-16 10:42:51 -04:00
|
|
|
WeakPreAnimatedStorage = PreAnimatedStorage;
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------
|
|
|
|
|
// Only gather entity meta-data during SavePreAnimatedState - the actual values will be cached
|
|
|
|
|
// inside FDataLayerState::Apply
|
|
|
|
|
auto GatherDataLayers = [this, EntityMetaData, DataLayerSubsystem, PreAnimatedStorage](
|
|
|
|
|
FEntityAllocationIteratorItem Item,
|
|
|
|
|
TRead<FMovieSceneEntityID> EntityIDs,
|
2022-03-04 15:09:42 -05:00
|
|
|
TRead<FRootInstanceHandle> RootInstanceHandles,
|
2021-06-16 10:42:51 -04:00
|
|
|
TRead<FMovieSceneDataLayerComponentData> ComponentData)
|
|
|
|
|
{
|
|
|
|
|
const bool bRestoreState = Item.GetAllocationType().Contains(FBuiltInComponentTypes::Get()->Tags.RestoreState);
|
|
|
|
|
for (int32 Index = 0; Index < Item.GetAllocation()->Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
const UMovieSceneDataLayerSection* Section = ComponentData[Index].Section.Get();
|
|
|
|
|
if (Section)
|
|
|
|
|
{
|
|
|
|
|
FMovieSceneEntityID EntityID = EntityIDs[Index];
|
2022-03-04 15:09:42 -05:00
|
|
|
FRootInstanceHandle RootInstance = RootInstanceHandles[Index];
|
2021-06-16 10:42:51 -04:00
|
|
|
|
2022-03-15 13:52:28 -04:00
|
|
|
for (const UDataLayerAsset* DataLayerAsset : Section->GetDataLayerAssets())
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-05-05 15:15:33 -04:00
|
|
|
UDataLayerInstance* DataLayerInstance = DataLayerSubsystem->GetDataLayerInstanceFromAsset(DataLayerAsset);
|
2022-03-15 13:52:28 -04:00
|
|
|
if (DataLayerInstance)
|
2021-06-16 10:42:51 -04:00
|
|
|
{
|
2022-03-15 13:52:28 -04:00
|
|
|
FPreAnimatedStateEntry Entry = PreAnimatedStorage->MakeEntry(DataLayerInstance);
|
2021-06-16 10:42:51 -04:00
|
|
|
EntityMetaData->BeginTrackingEntity(Entry, EntityID, RootInstance, bRestoreState);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-01-27 14:35:51 -05:00
|
|
|
FComponentMask Filter{ BuiltInComponents->Tags.NeedsLink };
|
|
|
|
|
if (!Linker->PreAnimatedState.IsCapturingGlobalState())
|
|
|
|
|
{
|
|
|
|
|
// If we're not capturing global state, only visit entities with the RestoreState tag
|
|
|
|
|
Filter.Set(BuiltInComponents->Tags.RestoreState);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-16 10:42:51 -04:00
|
|
|
// Iterate any data layer components that need link
|
|
|
|
|
FEntityTaskBuilder()
|
|
|
|
|
.ReadEntityIDs()
|
|
|
|
|
.Read(BuiltInComponents->RootInstanceHandle)
|
|
|
|
|
.Read(TracksComponents->DataLayer)
|
2022-01-27 14:35:51 -05:00
|
|
|
.FilterAll(Filter)
|
2021-06-16 10:42:51 -04:00
|
|
|
.Iterate_PerAllocation(&Linker->EntityManager, GatherDataLayers);
|
|
|
|
|
}
|
|
|
|
|
|