// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Array.h" #include "Containers/ArrayView.h" #include "Containers/ContainerAllocationPolicies.h" #include "Containers/Set.h" #include "Containers/UnrealString.h" #include "CoreMinimal.h" #include "CoreTypes.h" #include "EntitySystem/MovieSceneEntityIDs.h" #include "EntitySystem/MovieSceneEntitySystemTypes.h" #include "Evaluation/MovieSceneEvaluationKey.h" #include "Evaluation/MovieSceneEvaluationTree.h" #include "Evaluation/MovieSceneSegment.h" #include "Evaluation/MovieSceneTrackIdentifier.h" #include "Math/NumericLimits.h" #include "Math/Range.h" #include "Misc/FrameNumber.h" #include "Misc/Guid.h" #include "MovieSceneFrameMigration.h" #include "MovieSceneSequenceID.h" #include "Serialization/Archive.h" #include "Templates/Function.h" #include "Templates/TypeHash.h" #include "Templates/UnrealTemplate.h" #include "UObject/Class.h" #include "UObject/ObjectMacros.h" #include "UObject/WeakObjectPtr.h" #include "UObject/WeakObjectPtrTemplates.h" #include "MovieSceneEvaluationField.generated.h" class UMovieSceneSequence; class UObject; struct FFrameNumber; struct FMovieSceneSequenceHierarchy; struct IMovieSceneSequenceTemplateStore; class UMovieSceneCondition; /** * A key that uniquely identifies an entity by its owner and ID */ USTRUCT() struct FMovieSceneEvaluationFieldEntityKey { GENERATED_BODY() friend bool operator==(FMovieSceneEvaluationFieldEntityKey A, FMovieSceneEvaluationFieldEntityKey B) { return A.EntityOwner == B.EntityOwner && A.EntityID == B.EntityID; } friend bool operator!=(FMovieSceneEvaluationFieldEntityKey A, FMovieSceneEvaluationFieldEntityKey B) { return !(A == B); } friend uint32 GetTypeHash(FMovieSceneEvaluationFieldEntityKey In) { return GetTypeHash(In.EntityOwner) ^ In.EntityID; } /** The entity owner - either a UMovieSceneSection or perhaps a UMovieSceneTrack. Must implement the IMovieSceneEntityProvider interface */ UPROPERTY() TWeakObjectPtr EntityOwner; /** The identifer for the entity within the owner. Normally this will be irrelevant (and 0), but may be used to identifier unique entities by index, or flags */ UPROPERTY() uint32 EntityID = 0; }; USTRUCT() struct FMovieSceneEvaluationFieldEntity { public: GENERATED_BODY() FMovieSceneEvaluationFieldEntity() : SharedMetaDataIndex(INDEX_NONE) {} FMovieSceneEvaluationFieldEntity(const FMovieSceneEvaluationFieldEntityKey& InKey, int32 InSharedMetaDataIndex = INDEX_NONE) : Key(InKey) , SharedMetaDataIndex(InSharedMetaDataIndex) {} UPROPERTY() FMovieSceneEvaluationFieldEntityKey Key; UPROPERTY() int32 SharedMetaDataIndex; }; USTRUCT() struct FMovieSceneEvaluationFieldSharedEntityMetaData { GENERATED_BODY() UPROPERTY() FGuid ObjectBindingID; }; USTRUCT() struct FMovieSceneEvaluationFieldEntityMetaData { GENERATED_BODY() FMovieSceneEvaluationFieldEntityMetaData() : ForcedTime(TNumericLimits::Lowest()) , Flags(ESectionEvaluationFlags::None) , bEvaluateInSequencePreRoll(false) , bEvaluateInSequencePostRoll(false) {} bool IsRedundant() const { return *this == FMovieSceneEvaluationFieldEntityMetaData(); } friend bool operator==(const FMovieSceneEvaluationFieldEntityMetaData& A, const FMovieSceneEvaluationFieldEntityMetaData& B) { return A.ForcedTime == B.ForcedTime && A.Flags == B.Flags && A.bEvaluateInSequencePreRoll == B.bEvaluateInSequencePreRoll && A.bEvaluateInSequencePostRoll == B.bEvaluateInSequencePostRoll && A.OverrideBoundPropertyPath == B.OverrideBoundPropertyPath && A.Condition == B.Condition; } /* Optional condition that the entity can provide to be checked at runtime before import. If the condition fails, the entity will not be imported. */ UPROPERTY() TSoftObjectPtr Condition; /** Opt-in - when this value is set, the entity should use this property path instead of the one defined on its generating section */ UPROPERTY() FString OverrideBoundPropertyPath; UPROPERTY() FFrameNumber ForcedTime; UPROPERTY() ESectionEvaluationFlags Flags; /** Opt-in - when no meta-data is present, or this value is false, this entity cannot be evaluated as part of sub-sequence preroll */ UPROPERTY() uint8 bEvaluateInSequencePreRoll : 1; /** Opt-in - when no meta-data is present, or this value is false, this entity cannot be evaluated as part of sub-sequence postroll */ UPROPERTY() uint8 bEvaluateInSequencePostRoll : 1; }; struct FMovieSceneEvaluationFieldEntityQuery { FMovieSceneEvaluationFieldEntity Entity; int32 MetaDataIndex; }; struct FMovieSceneEvaluationFieldEntityKeyFuncs : BaseKeyFuncs { static FORCEINLINE FMovieSceneEvaluationFieldEntityKey GetSetKey(const FMovieSceneEvaluationFieldEntityQuery& Element) { return Element.Entity.Key; } static FORCEINLINE bool Matches(const FMovieSceneEvaluationFieldEntityKey& A, const FMovieSceneEvaluationFieldEntityKey& B) { return A == B; } static FORCEINLINE uint32 GetKeyHash(const FMovieSceneEvaluationFieldEntityKey& Key) { return GetTypeHash(Key); } }; using FMovieSceneEvaluationFieldEntitySet = TSet; USTRUCT() struct FMovieSceneEvaluationFieldEntityTree { GENERATED_BODY() bool Serialize(FArchive& Ar) { Ar << SerializedData; return true; } bool Identical(const FMovieSceneEvaluationFieldEntityTree* Other, uint32 PortFlags) const { return Other->SerializedData == SerializedData; } struct FEntityAndMetaDataIndex { int32 EntityIndex; int32 MetaDataIndex; friend FArchive& operator<<(FArchive& Ar, FEntityAndMetaDataIndex& In) { return Ar << In.EntityIndex << In.MetaDataIndex; } friend bool operator==(const FEntityAndMetaDataIndex& A, const FEntityAndMetaDataIndex& B) { return A.EntityIndex == B.EntityIndex && A.MetaDataIndex == B.MetaDataIndex; } }; TMovieSceneEvaluationTree SerializedData; }; template<> struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 { enum { WithSerializer = true, WithIdentical = true, WithCopy = false }; }; /** * High-level container which acts as a look-up-table for IMovieSceneEntityProviders and their entities and meta-data in a sequence * * Generally generated and accessed through UMovieSceneCompiledDataManager, but can also be used independently. * Entity fields are constructed using FMovieSceneEntityComponentFieldBuilder which ensures the invariants of this class are * maintained along with guaranteeing no redundant entries exist. */ USTRUCT() struct FMovieSceneEntityComponentField { GENERATED_BODY() /** * Check if this field is empty */ bool IsEmpty() const { return Entities.Num() == 0; } /** * Retrieve an entity from its index */ const FMovieSceneEvaluationFieldEntity& GetEntity(int32 EntityIndex) const { return Entities[EntityIndex]; } /** * Retrieve the meta-data for an entity * @return The meta-data for an entity or nullptr if it has none associated with it */ const FMovieSceneEvaluationFieldEntityMetaData* FindMetaData(const FMovieSceneEvaluationFieldEntityQuery& InQuery) const { return InQuery.MetaDataIndex != INDEX_NONE ? &EntityMetaData[InQuery.MetaDataIndex] : nullptr; } /** * Retrieve the shared meta-data for an entity * @return The shared meta-data for an entity or nullptr if it has none associated with it */ const FMovieSceneEvaluationFieldSharedEntityMetaData* FindSharedMetaData(const FMovieSceneEvaluationFieldEntityQuery& InQuery) const { return InQuery.Entity.SharedMetaDataIndex != INDEX_NONE ? &SharedMetaData[InQuery.Entity.SharedMetaDataIndex] : nullptr; } /** * Query the persistent entities for any given time within a sequence. * @note: Persistent entities should remain alive until they are no longer present at the current time. * * @param QueryTime The time at which to query the field (in the TickResolution of the sequence this was generated from) * @param OutRange Will receive the hull of the range that was intersected for which the resulting OutEntities remains constant * @param OutEntities A set that will be populated with all the entities that exist at the specified time */ MOVIESCENE_API void QueryPersistentEntities(FFrameNumber QueryTime, TRange& OutRange, FMovieSceneEvaluationFieldEntitySet& OutEntities) const; /** * Query the persistent entities for any given time within a sequence. * @note: Persistent entities should remain alive until they are no longer present at the current time. * * @param QueryTime The time at which to query the field (in the TickResolution of the sequence this was generated from) * @param QueryCallback A handler for dealing with the resulting entities * @param OutRange Will receive the hull of the range that was intersected for which the resulting OutEntities remains constant */ MOVIESCENE_API void QueryPersistentEntities(FFrameNumber QueryTime, TFunctionRef QueryCallback, TRange& OutRange) const; /** * Check whether this field contains any one-shot entities */ MOVIESCENE_API bool HasAnyOneShotEntities() const; /** * Query the one-shot entities that overlap with the specified query range. * @note: One-shot entities only ever live for a single frame of evaluation. * * @param QueryRange The ranger over which to query the field (in the TickResolution of the sequence this was generated from) * @param OutEntities A set that will be populated with all the entities that overlapped at all with the specified range */ MOVIESCENE_API void QueryOneShotEntities(const TRange& QueryRange, FMovieSceneEvaluationFieldEntitySet& OutEntityIndices) const; private: friend struct FMovieSceneEntityComponentFieldBuilder; /** A hierarchical tree specifiying indices into the Entities array for any given time such persistent entities are active */ UPROPERTY() FMovieSceneEvaluationFieldEntityTree PersistentEntityTree; /** A hierarchical tree specifiying indices into the Entities array for any given time such one-shot entities are active */ UPROPERTY() FMovieSceneEvaluationFieldEntityTree OneShotEntityTree; /** 16 bytes - Flat array of unique entities. The 2 tree types specify indices into this array */ UPROPERTY() TArray Entities; /** 16 bytes - Optional meta-data for specific entities. Specified in FMovieSceneEvaluationFieldEntity::MetaDataIndex. */ UPROPERTY() TArray EntityMetaData; /** 16 bytes - Optional shared meta-data for groups of entities. Specified in FMovieSceneEvaluationFieldEntity::SharedMetaDataIndex. */ UPROPERTY() TArray SharedMetaData; }; /** * Builder class used for populating an FMovieSceneEntityComponentField with data. * Ensures that null or redundant entities or meta-data are not added to the field, and that all indices are valid and correct. */ struct FMovieSceneEntityComponentFieldBuilder { static constexpr uint32 InvalidEntityID = ~0u; /** * Construction from a field to populate */ MOVIESCENE_API FMovieSceneEntityComponentFieldBuilder(FMovieSceneEntityComponentField* InField); /** * Destructor that cleans up redundant data if necessary */ MOVIESCENE_API ~FMovieSceneEntityComponentFieldBuilder(); /** * Access the shared meta-data for all the entities created by this builder. */ MOVIESCENE_API FMovieSceneEvaluationFieldSharedEntityMetaData& GetSharedMetaData(); /** * Access the index of the shared meta-data of this builder. */ MOVIESCENE_API int32 GetSharedMetaDataIndex() const; /** * Add meta-data to this tree returning its index within this builder * * @param InMetaData The meta-data to add. * @return A unique index for this meta-data within this builder, or INDEX_NONE if the meta-data is redundant */ MOVIESCENE_API int32 AddMetaData(const FMovieSceneEvaluationFieldEntityMetaData& InMetaData); /** * Retrieve an index for the entity that is identified by the specified owner and ID * * @param EntityOwner The owner that produces the entity at runtime. Must implement the IMovieSceneEntityProvider interface * @param EntityID (Optional) An identifier used to identify the entity inside IMovieSceneEntityProvider::ImportEntityImpl. Could be an index within an array or a set of flags. * @return An index into this builder used to uniquely identify this entity. */ MOVIESCENE_API int32 FindOrAddEntity(UObject* EntityOwner, uint32 EntityID = 0); /** * Add a persistent entity to the field for a given range. Equivalent to AddPersistentEntity(Range, FindOrAddEntity(EntityOwner, EntityID)). * @note: Persistent entities remain alive for the entire duration of their applicable ranges. * * @param Range The range within which this entity should be alive * @param EntityOwner The owner that produces the entity at runtime. Must implement the IMovieSceneEntityProvider interface * @param EntityID (Optional) An identifier used to identify the entity inside IMovieSceneEntityProvider::ImportEntityImpl. Could be an index within an array or a set of flags. * @param MetaDataIndex (Optional) Meta-data to use for this entitiy within this range. See AddMetaData. */ MOVIESCENE_API void AddPersistentEntity(const TRange& Range, UObject* EntityOwner, uint32 EntityID = 0, int32 InMetaDataIndex = INDEX_NONE); /** * Add a persistent entity to the field for a given range * @note: Persistent entities remain alive for the entire duration of their applicable ranges. * * @param Range The range within which this entity should be alive * @param LocalIndex The index to the entity retrieved from FindOrAddEntity. * @param MetaDataIndex (Optional) Meta-data to use for this entitiy within this range. See AddMetaData. */ MOVIESCENE_API void AddPersistentEntity(const TRange& Range, int32 LocalIndex, int32 InMetaDataIndex = INDEX_NONE); /** * Add a one-shot entity to the field for a given range. Equivalent to AddOneShotEntity(Range, FindOrAddEntity(EntityOwner, EntityID)). * @note: One-shot entities are only ever alive for a single evaluation, regardless of the range within the field. This makes them ideal for events or triggers. * * @param Range The range within which this entity should be alive * @param EntityOwner The owner that produces the entity at runtime. Must implement the IMovieSceneEntityProvider interface * @param EntityID (Optional) An identifier used to identify the entity inside IMovieSceneEntityProvider::ImportEntityImpl. Could be an index within an array or a set of flags. * @param MetaDataIndex (Optional) Meta-data to use for this entitiy within this range. See AddMetaData. */ MOVIESCENE_API void AddOneShotEntity(const TRange& OneShotRange, UObject* EntityOwner, uint32 EntityID = 0, int32 InMetaDataIndex = INDEX_NONE); /** * Add a one-shot entity to the field for a given range * @note: One-shot entities are only ever alive for a single evaluation, regardless of the range within the field. This makes them ideal for events or triggers. * * @param Range The range within which this entity should be alive * @param LocalIndex The index to the entity retrieved from FindOrAddEntity. * @param MetaDataIndex (Optional) Meta-data to use for this entitiy within this range. See AddMetaData. */ MOVIESCENE_API void AddOneShotEntity(const TRange& OneShotRange, int32 LocalIndex, int32 InMetaDataIndex = INDEX_NONE); private: /** Convert a user-facing local index into KeyToFieldIndex, into an index within FMovieSceneEntityComponentField::Entities */ MOVIESCENE_API int32 LocalEntityIndexToFieldIndex(int32 LocalIndex); /** Convert a user-facing local meta-data index into MetaDataToFieldIndex, into an index within FMovieSceneEntityComponentField::EntityMetaData */ MOVIESCENE_API int32 LocalMetaDataIndexToFieldIndex(int32 LocalIndex); /** Array of entity keys and their field index within FMovieSceneEntityComponentField::Entities */ struct FKeyToIndex { FMovieSceneEvaluationFieldEntityKey Key; int32 FieldIndex; }; TArray> KeyToFieldIndex; struct FMetaDataToIndex { FMovieSceneEvaluationFieldEntityMetaData MetaData; int32 FieldIndex; }; TArray> MetaDataToFieldIndex; /** The field that we are building */ FMovieSceneEntityComponentField* Field; /** (default: INDEX_NONE) The index into FMovieSceneEntityComponentField::SharedMetaData for all entities built by this builder, if it has been defined. */ int32 SharedMetaDataIndex; }; //--------------------------------------------------------- // Legacy track template field structures begin here //--------------------------------------------------------- /** A pointer to a track held within an evaluation template */ USTRUCT() struct FMovieSceneEvaluationFieldTrackPtr { GENERATED_BODY() /** * Default constructor */ FMovieSceneEvaluationFieldTrackPtr(){} /** * Construction from a sequence ID, and the index of the track within that sequence's track list */ FMovieSceneEvaluationFieldTrackPtr(FMovieSceneSequenceIDRef InSequenceID, FMovieSceneTrackIdentifier InTrackIdentifier) : SequenceID(InSequenceID) , TrackIdentifier(InTrackIdentifier) {} /** * Check for equality */ friend bool operator==(FMovieSceneEvaluationFieldTrackPtr A, FMovieSceneEvaluationFieldTrackPtr B) { return A.TrackIdentifier == B.TrackIdentifier && A.SequenceID == B.SequenceID; } /** * Get a hashed representation of this type */ friend uint32 GetTypeHash(FMovieSceneEvaluationFieldTrackPtr LHS) { return HashCombine(GetTypeHash(LHS.TrackIdentifier), GetTypeHash(LHS.SequenceID)); } /** The sequence ID that identifies to which sequence the track belongs */ UPROPERTY() FMovieSceneSequenceID SequenceID; /** The Identifier of the track inside the track map (see FMovieSceneEvaluationTemplate::Tracks) */ UPROPERTY() FMovieSceneTrackIdentifier TrackIdentifier; }; /** A pointer to a particular segment of a track held within an evaluation template */ USTRUCT() struct FMovieSceneEvaluationFieldSegmentPtr : public FMovieSceneEvaluationFieldTrackPtr { GENERATED_BODY() /** * Default constructor */ FMovieSceneEvaluationFieldSegmentPtr(){} /** * Construction from a sequence ID, and the index of the track within that sequence's track list */ FMovieSceneEvaluationFieldSegmentPtr(FMovieSceneSequenceIDRef InSequenceID, FMovieSceneTrackIdentifier InTrackIdentifier, FMovieSceneSegmentIdentifier InSegmentID) : FMovieSceneEvaluationFieldTrackPtr(InSequenceID, InTrackIdentifier) , SegmentID(InSegmentID) {} /** * Check for equality */ friend bool operator==(FMovieSceneEvaluationFieldSegmentPtr A, FMovieSceneEvaluationFieldSegmentPtr B) { return A.SegmentID == B.SegmentID && A.TrackIdentifier == B.TrackIdentifier && A.SequenceID == B.SequenceID; } /** * Get a hashed representation of this type */ friend uint32 GetTypeHash(FMovieSceneEvaluationFieldSegmentPtr LHS) { return HashCombine(GetTypeHash(LHS.SegmentID), GetTypeHash(static_cast(LHS))); } /** The identifier of the segment within the track (see FMovieSceneEvaluationTrack::Segments) */ UPROPERTY() FMovieSceneSegmentIdentifier SegmentID; }; USTRUCT() struct FMovieSceneFieldEntry_EvaluationTrack { GENERATED_BODY() UPROPERTY() FMovieSceneEvaluationFieldTrackPtr TrackPtr; UPROPERTY() uint16 NumChildren = 0; }; USTRUCT() struct FMovieSceneFieldEntry_ChildTemplate { GENERATED_BODY() FMovieSceneFieldEntry_ChildTemplate() : ChildIndex(-1) , Flags(ESectionEvaluationFlags::None) , ForcedTime(TNumericLimits::Lowest()) {} FMovieSceneFieldEntry_ChildTemplate(uint16 InChildIndex, ESectionEvaluationFlags InFlags, FFrameNumber InForcedTime) : ChildIndex(InChildIndex) , Flags(InFlags) , ForcedTime(InForcedTime) {} UPROPERTY() uint16 ChildIndex; UPROPERTY() ESectionEvaluationFlags Flags; UPROPERTY() FFrameNumber ForcedTime; }; /** Lookup table index for a group of evaluation templates */ USTRUCT() struct FMovieSceneEvaluationGroupLUTIndex { GENERATED_BODY() FMovieSceneEvaluationGroupLUTIndex() : NumInitPtrs(0) , NumEvalPtrs(0) {} /** The number of initialization pointers are stored after &FMovieSceneEvaluationGroup::SegmentPtrLUT[0] + LUTOffset. */ UPROPERTY() int32 NumInitPtrs; /** The number of evaluation pointers are stored after &FMovieSceneEvaluationGroup::SegmentPtrLUT[0] + LUTOffset + NumInitPtrs. */ UPROPERTY() int32 NumEvalPtrs; }; /** Holds segment pointers for all segments that are active for a given range of the sequence */ USTRUCT() struct FMovieSceneEvaluationGroup { GENERATED_BODY() /** Array of indices that define all the flush groups in the range. */ UPROPERTY() TArray LUTIndices; /** */ UPROPERTY() TArray TrackLUT; /** */ UPROPERTY() TArray SectionLUT; }; /** Struct that stores the key for an evaluated entity, and the index at which it was (or is to be) evaluated */ USTRUCT() struct FMovieSceneOrderedEvaluationKey { GENERATED_BODY() UPROPERTY() FMovieSceneEvaluationKey Key; UPROPERTY() uint16 SetupIndex = 0; UPROPERTY() uint16 TearDownIndex = 0; }; /** Informational meta-data that applies to a given time range */ USTRUCT() struct FMovieSceneEvaluationMetaData { GENERATED_BODY() /** * Reset this meta-data */ void Reset() { ActiveSequences.Reset(); ActiveEntities.Reset(); } /** * Diff the active sequences this frame, with the specified previous frame's meta-data * * @param LastFrame Meta-data pertaining to the last frame * @param NewSequences (Optional) Ptr to an array that will be populated with sequences that are new this frame * @param ExpiredSequences (Optional) Ptr to an array that will be populated with sequences that are no longer being evaluated */ void DiffSequences(const FMovieSceneEvaluationMetaData& LastFrame, TArray* NewSequences, TArray* ExpiredSequences) const; /** * Diff the active entities (tracks and sections) this frame, with the specified previous frame's meta-data * * @param LastFrame Meta-data pertaining to the last frame * @param NewKeys (Optional) Ptr to an array that will be populated with entities that are new this frame * @param ExpiredKeys (Optional) Ptr to an array that will be populated with entities that are no longer being evaluated */ void DiffEntities(const FMovieSceneEvaluationMetaData& LastFrame, TArray* NewKeys, TArray* ExpiredKeys) const; /** Array of sequences that are active in this time range. */ UPROPERTY() TArray ActiveSequences; /** Array of entities (tracks and/or sections) that are active in this time range. */ UPROPERTY() TArray ActiveEntities; }; /** * Memory layout optimized primarily for speed of searching the applicable ranges */ USTRUCT() struct FMovieSceneEvaluationField { GENERATED_BODY() /** * Efficiently find the entry that exists at the specified time, if any * * @param Time The time at which to seach * @return The index within Ranges, Groups and MetaData that the current time resides, or INDEX_NONE if there is nothing to do at the requested time */ MOVIESCENE_API int32 GetSegmentFromTime(FFrameNumber Time) const; /** * Deduce the indices into Ranges and Groups that overlap with the specified time range * * @param Range The range to overlap with our field * @return A range of indices for which GetRange() overlaps the specified Range, of the form [First, First+Num) */ MOVIESCENE_API TRange OverlapRange(const TRange& Range) const; /** * Invalidate a range in this field * * @param Range The range to overlap with our field * @return A range of indices into Ranges and Groups that overlap with the requested range */ MOVIESCENE_API void Invalidate(const TRange& Range); /** * Insert a new range into this field * * @param InRange The total range to insert to the field. Will potentially be intersected with preexisting adjacent ranges * @param InGroup The group defining what should happen at this time * @param InMetaData The meta-data defining efficient access to what happens in this frame * @return The index the entries were inserted at */ MOVIESCENE_API int32 Insert(const TRange& InRange, FMovieSceneEvaluationGroup&& InGroup, FMovieSceneEvaluationMetaData&& InMetaData); /** * Add the specified data to this field, assuming the specified range lies after any other entries * * @param InRange The range to add * @param InGroup The group defining what should happen at this time * @param InMetaData The meta-data defining efficient access to what happens in this frame */ MOVIESCENE_API void Add(const TRange& InRange, FMovieSceneEvaluationGroup&& InGroup, FMovieSceneEvaluationMetaData&& InMetaData); /** * Access this field's signature */ #if WITH_EDITORONLY_DATA const FGuid& GetSignature() const { return Signature; } #endif /** * Access this field's size */ int32 Size() const { return Ranges.Num(); } /** * Access this entire field's set of ranges */ TArrayView GetRanges() const { return Ranges; } /** * Lookup a valid range by index * @param Index The valid index within the ranges to lookup * @return The range */ const TRange& GetRange(int32 Index) const { return Ranges[Index].Value; } /** * Lookup a valid evaluation group by entry index * @param Index The valid index within the evaluation group array to lookup * @return The group */ const FMovieSceneEvaluationGroup& GetGroup(int32 Index) const { return Groups[Index]; } /** * Lookup valid meta-data by entry index * @param Index The valid index within the meta-data array to lookup * @return The meta-data */ const FMovieSceneEvaluationMetaData& GetMetaData(int32 Index) const { return MetaData[Index]; } private: #if WITH_EDITORONLY_DATA /** Signature that uniquely identifies any state this field can be in - regenerated on mutation */ UPROPERTY() FGuid Signature; #endif /** Ranges stored separately for fast (cache efficient) lookup. Each index has a corresponding entry in FMovieSceneEvaluationField::Groups. */ UPROPERTY() TArray Ranges; /** Groups that store segment pointers for each of the above ranges. Each index has a corresponding entry in FMovieSceneEvaluationField::Ranges. */ UPROPERTY() TArray Groups; /** Meta data that maps to entries in the 'Ranges' array. */ UPROPERTY() TArray MetaData; };