// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Async/TaskGraphInterfaces.h" #include "Containers/Array.h" #include "Containers/ArrayView.h" #include "Containers/BitArray.h" #include "Containers/ContainerAllocationPolicies.h" #include "Containers/SortedMap.h" #include "Containers/SparseArray.h" #include "Containers/UnrealString.h" #include "EntitySystem/MovieSceneEntitySystemDirectedGraph.h" #include "EntitySystem/MovieSceneEntitySystemTypes.h" #include "HAL/Platform.h" #include "HAL/PlatformCrt.h" #include "Math/NumericLimits.h" #include "Misc/AssertionMacros.h" #include "Templates/Casts.h" #include "Templates/SharedPointer.h" #include "Templates/SubclassOf.h" #include "UObject/Class.h" #include "UObject/Object.h" #include "UObject/ObjectMacros.h" #include "UObject/ObjectPtr.h" #include "MovieSceneEntitySystemGraphs.generated.h" class FReferenceCollector; class UMovieSceneEntitySystem; class UMovieSceneEntitySystemLinker; template class TFunctionRef; namespace UE { namespace MovieScene { struct FSystemSubsequentTasks; struct FSystemTaskPrerequisites; class FEntityManager; class FEntitySystemScheduler; } // namespace MovieScene } // namespace UE USTRUCT() struct FMovieSceneEntitySystemGraphNode { GENERATED_BODY(); FMovieSceneEntitySystemGraphNode() : System(nullptr) {} explicit FMovieSceneEntitySystemGraphNode(UMovieSceneEntitySystem* InSystem) : System(InSystem) {} TSharedPtr Prerequisites; TSharedPtr SubsequentTasks; UPROPERTY() TObjectPtr System; }; USTRUCT() struct FMovieSceneEntitySystemGraphNodes { GENERATED_BODY() void AddStructReferencedObjects(FReferenceCollector& Collector) const; TSparseArray Array; }; template<> struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 { enum { WithAddStructReferencedObjects = true }; }; USTRUCT() struct FMovieSceneEntitySystemGraph { using FDirectionalEdge = UE::MovieScene::FDirectedGraph::FDirectionalEdge; GENERATED_BODY() MOVIESCENE_API FMovieSceneEntitySystemGraph(); MOVIESCENE_API ~FMovieSceneEntitySystemGraph(); FMovieSceneEntitySystemGraph(const FMovieSceneEntitySystemGraph&) = delete; void operator=(const FMovieSceneEntitySystemGraph&) = delete; MOVIESCENE_API FMovieSceneEntitySystemGraph(FMovieSceneEntitySystemGraph&&); MOVIESCENE_API FMovieSceneEntitySystemGraph& operator=(FMovieSceneEntitySystemGraph&&); MOVIESCENE_API void AddReference(UMovieSceneEntitySystem* FromReference, UMovieSceneEntitySystem* ToReference); MOVIESCENE_API void RemoveReference(UMovieSceneEntitySystem* FromReference, UMovieSceneEntitySystem* ToReference); /** Olog(n) time */ template void GatherReferencesFrom(const UMovieSceneEntitySystem* FromReference, TArray& OutReferences) { IterateReferences(FromReference, [&OutReferences](UMovieSceneEntitySystem* System){ OutReferences.Add(System); }); } template void IterateReferencesFrom(const UMovieSceneEntitySystem* FromReference, Iter&& Iterator) { check(GetGraphID(FromReference) != TNumericLimits::Max()); for (const FDirectionalEdge& Edge : ReferenceGraph.GetEdgesFrom(GetGraphID(FromReference))) { Iterator(Nodes.Array[Edge.ToNode]); } } /** O(n) time */ template void GatherReferencesTo(const UMovieSceneEntitySystem* ToReference, TArray& OutReferences) { IterateReferences(ToReference, [&OutReferences](UMovieSceneEntitySystem* System){ OutReferences.Add(System); }); } template void IterateReferencesTo(const UMovieSceneEntitySystem* ToReference, Iter&& Iterator) { const uint16 ToNode = GetGraphID(ToReference); check(ToNode != TNumericLimits::Max()); for (const FDirectionalEdge& Edge : ReferenceGraph.GetEdges()) { if (Edge.ToNode == ToNode) { Iterator(Nodes.Array[Edge.FromNode]); } } } bool IsEmpty() const { return Nodes.Array.Num() == 0; } bool HasReferencesTo(const UMovieSceneEntitySystem* ToReference) const { return ReferenceGraph.HasEdgeTo(GetGraphID(ToReference)); } bool HasReferencesFrom(const UMovieSceneEntitySystem* FromReference) const { return ReferenceGraph.HasEdgeFrom(GetGraphID(FromReference)); } MOVIESCENE_API void AddSystem(UMovieSceneEntitySystem* InSystem); MOVIESCENE_API void RemoveSystem(UMovieSceneEntitySystem* InSystem); MOVIESCENE_API int32 RemoveIrrelevantSystems(UMovieSceneEntitySystemLinker* Linker); MOVIESCENE_API void Shutdown(); MOVIESCENE_API int32 NumInPhase(UE::MovieScene::ESystemPhase Phase) const; MOVIESCENE_API void ExecutePhase(UE::MovieScene::ESystemPhase Phase, UMovieSceneEntitySystemLinker* Linker, FGraphEventArray& OutTasks); MOVIESCENE_API void IteratePhase(UE::MovieScene::ESystemPhase Phase, TFunctionRef InIter); MOVIESCENE_API void ReconstructTaskSchedule(UE::MovieScene::FEntityManager* EntityManager); MOVIESCENE_API void ScheduleTasks(UE::MovieScene::FEntityManager* EntityManager); MOVIESCENE_API TArray GetSystems() const; template SystemType* FindSystemOfType() const { return CastChecked(FindSystemOfType(SystemType::StaticClass()), ECastCheckedType::NullAllowed); } MOVIESCENE_API UMovieSceneEntitySystem* FindSystemOfType(TSubclassOf InClassType) const; MOVIESCENE_API void DebugPrint() const; MOVIESCENE_API FString ToString() const; private: // Implementation function that means we don't need to #include the entity system static MOVIESCENE_API uint16 GetGraphID(const UMovieSceneEntitySystem* InSystem); MOVIESCENE_API void UpdateCache(); template void ExecutePhase(UE::MovieScene::ESystemPhase Phase, const ArrayType& RetrieveEntries, UMovieSceneEntitySystemLinker* Linker, FGraphEventArray& OutTasks); private: friend UE::MovieScene::FSystemSubsequentTasks; TArray> SpawnPhase; TArray> InstantiationPhase; TArray> SchedulingPhase; TArray> EvaluationPhase; TArray> FinalizationPhase; TUniquePtr TaskScheduler; UPROPERTY() FMovieSceneEntitySystemGraphNodes Nodes; TMap GlobalToLocalNodeIDs; UE::MovieScene::FDirectedGraph ReferenceGraph; uint64 SchedulerSerialNumber = 0; uint32 SerialNumber = 0; uint32 PreviousSerialNumber = 0; uint32 ReentrancyGuard = 0; }; template<> struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 { enum { WithCopy = false }; };