// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Array.h" #include "CoreMinimal.h" #include "Evaluation/MovieSceneAnimTypeID.h" #include "HAL/Platform.h" #include "Misc/InlineValue.h" #include "Misc/Optional.h" #include "Templates/Decay.h" #include "Templates/SharedPointer.h" #include "Templates/UnrealTemplate.h" class UObject; struct FMovieSceneBlendingAccumulator; struct FMovieSceneContext; template struct TMovieSceneInterrogationIterator; /** Key used for populating template interrogation data */ struct FMovieSceneInterrogationKey { /** Unique identifier for the type of data that resulted from the interrogation - doesn't at all have to relate to any FMovieSceneAnimTypeIDs used at runtime */ FMovieSceneAnimTypeID AnimTypeID; FMovieSceneInterrogationKey(FMovieSceneAnimTypeID InAnimTypeID) : AnimTypeID(InAnimTypeID) {} friend bool operator==(FMovieSceneInterrogationKey A, FMovieSceneInterrogationKey B) { return A.AnimTypeID == B.AnimTypeID; } friend bool operator!=(FMovieSceneInterrogationKey A, FMovieSceneInterrogationKey B) { return A.AnimTypeID != B.AnimTypeID; } /** * Access the interrogation key for transform data - any interrogation data stored with this key is guaranteed to be of type 'FTransform' * to be used by various editors and sections that reference transforms */ MOVIESCENE_API static FMovieSceneInterrogationKey GetTransformInterrogationKey(); }; /** Tokens that are stored in FMovieSceneInterrogationData */ struct IMovieSceneInterrogationToken { FMovieSceneInterrogationKey Key; IMovieSceneInterrogationToken(FMovieSceneInterrogationKey InKey) : Key(InKey) {} }; template struct TMovieSceneInterrogationToken : IMovieSceneInterrogationToken { T Data; template TMovieSceneInterrogationToken(U&& In, FMovieSceneInterrogationKey InKey) : IMovieSceneInterrogationToken(InKey) , Data(Forward(In)) { } }; /** * Data structure that is passed to all tracks and templates when interrogating them for data. * Used by FMovieSceneEvaluationTrack::Interrogate */ struct FMovieSceneInterrogationData { /** * Add arbitrary data to the container under the specified key. * Care should be taken by clients to ensure that data types that are added with specific keys are always accessed as the correct types */ template void Add(T&& InData, FMovieSceneInterrogationKey Key) { TokenData.Add(TMovieSceneInterrogationToken::Type>(Forward(InData), Key)); } /** * Iterate all data stored in this container */ TArray>::TConstIterator Iterate() const { return TokenData.CreateConstIterator(); } /** * Iterate any data in this container that matches the specified key * Care should be taken by clients to ensure that data types that are added with specific keys are always accessed as the correct types */ template TMovieSceneInterrogationIterator Iterate(FMovieSceneInterrogationKey Key) const { return TMovieSceneInterrogationIterator(*this, Key); } MOVIESCENE_API void Finalize(const FMovieSceneContext& Context, UObject* BindingOverride); MOVIESCENE_API FMovieSceneBlendingAccumulator& GetAccumulator(); private: template friend struct TMovieSceneInterrogationIterator; TArray> TokenData; /** Optional accumulator that is allocated when required */ TSharedPtr Accumulator; }; template struct TMovieSceneInterrogationIterator { TMovieSceneInterrogationIterator(const FMovieSceneInterrogationData& InContainer, FMovieSceneInterrogationKey InPredicateKey) : Container(InContainer) , PredicateKey(InPredicateKey) , Index(-1) { NextElement(); } TMovieSceneInterrogationIterator& operator++() { NextElement(); return *this; } const DataType& operator*() const { return static_cast&>(Container.TokenData[Index].GetValue()).Data; } const DataType* operator->() const { return &static_cast&>(Container.TokenData[Index].GetValue()).Data; } FORCEINLINE explicit operator bool() const { return Container.TokenData.IsValidIndex(Index); } FORCEINLINE bool operator!() const { return !(bool)*this; } FORCEINLINE friend bool operator==(const TMovieSceneInterrogationIterator& LHS, const TMovieSceneInterrogationIterator& RHS) { return &LHS.Container == &RHS.Container && LHS.Index == RHS.Index; } FORCEINLINE friend bool operator!=(const TMovieSceneInterrogationIterator& LHS, const TMovieSceneInterrogationIterator& RHS) { return &LHS.Container != &RHS.Container || LHS.Index != RHS.Index; } FORCEINLINE friend TMovieSceneInterrogationIterator begin(const TMovieSceneInterrogationIterator& In) { return In; } FORCEINLINE friend TMovieSceneInterrogationIterator end( const TMovieSceneInterrogationIterator& In) { TMovieSceneInterrogationIterator New = In; New.Index = -1; return New; } void NextElement() { while (Container.TokenData.IsValidIndex(++Index)) { if (!PredicateKey.IsSet() || Container.TokenData[Index]->Key == PredicateKey) { break; } } if (!Container.TokenData.IsValidIndex(Index)) { Index = -1; } } private: const FMovieSceneInterrogationData& Container; TOptional PredicateKey; int32 Index; };