Files
UnrealEngine/Engine/Source/Runtime/MovieScene/Public/Compilation/MovieSceneTemplateInterrogation.h
2025-05-18 13:04:45 +08:00

178 lines
5.4 KiB
C++

// 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<typename T> 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<typename T>
struct TMovieSceneInterrogationToken : IMovieSceneInterrogationToken
{
T Data;
template<typename U> TMovieSceneInterrogationToken(U&& In, FMovieSceneInterrogationKey InKey)
: IMovieSceneInterrogationToken(InKey)
, Data(Forward<U>(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<typename T>
void Add(T&& InData, FMovieSceneInterrogationKey Key)
{
TokenData.Add(TMovieSceneInterrogationToken<typename TDecay<T>::Type>(Forward<T>(InData), Key));
}
/**
* Iterate all data stored in this container
*/
TArray<TInlineValue<IMovieSceneInterrogationToken>>::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<typename T>
TMovieSceneInterrogationIterator<T> Iterate(FMovieSceneInterrogationKey Key) const
{
return TMovieSceneInterrogationIterator<T>(*this, Key);
}
MOVIESCENE_API void Finalize(const FMovieSceneContext& Context, UObject* BindingOverride);
MOVIESCENE_API FMovieSceneBlendingAccumulator& GetAccumulator();
private:
template<typename T> friend struct TMovieSceneInterrogationIterator;
TArray<TInlineValue<IMovieSceneInterrogationToken>> TokenData;
/** Optional accumulator that is allocated when required */
TSharedPtr<FMovieSceneBlendingAccumulator> Accumulator;
};
template<typename DataType>
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<const TMovieSceneInterrogationToken<DataType>&>(Container.TokenData[Index].GetValue()).Data;
}
const DataType* operator->() const
{
return &static_cast<const TMovieSceneInterrogationToken<DataType>&>(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<DataType> begin(const TMovieSceneInterrogationIterator<DataType>& In) { return In; }
FORCEINLINE friend TMovieSceneInterrogationIterator<DataType> end( const TMovieSceneInterrogationIterator<DataType>& In) { TMovieSceneInterrogationIterator<DataType> 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<FMovieSceneInterrogationKey> PredicateKey;
int32 Index;
};