// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "EntitySystem/MovieSceneEntityIDs.h" #include "EntitySystem/MovieSceneEntityInstantiatorSystem.h" #include "EntitySystem/BuiltInComponentTypes.h" #include "EntitySystem/MovieSceneEntitySystemTypes.h" #include "EntitySystem/MovieScenePropertyComponentHandler.h" #include "EntitySystem/MovieSceneOverlappingEntityTracker.h" #include "MovieSceneInterrogatedPropertyInstantiator.generated.h" class UMovieSceneBlenderSystem; /** Class responsible for resolving all property types registered with FBuiltInComponentTypes::PropertyRegistry */ UCLASS(MinimalAPI) class UMovieSceneInterrogatedPropertyInstantiatorSystem : public UMovieSceneEntityInstantiatorSystem { public: using FMovieSceneEntityID = UE::MovieScene::FMovieSceneEntityID; using FValueRecompositionResult = UE::MovieScene::TRecompositionResult; GENERATED_BODY() MOVIESCENETRACKS_API UMovieSceneInterrogatedPropertyInstantiatorSystem(const FObjectInitializer& ObjInit); /** * Recompose a value from the constituent parts specified in InQuery, taking into accounts the wieghtings of the specific channel defined by ChannelCompositeIndex. * * @param PropertyDefinition The property that this float channel is bound to * @param ChannelCompositeIndex The index of the composite that this float channel represents, if it is part of a composite value (for instance when keying/recomposing Translation.Z) * @param InQuery The query defining the entities and object to recompose * @param InCurrentValue The value of the property to recompose * @return A result containing the recomposed value for each of the entities specified in InQuery */ MOVIESCENETRACKS_API FValueRecompositionResult RecomposeBlendChannel(const UE::MovieScene::FPropertyDefinition& PropertyDefinition, int32 ChannelCompositeIndex, const UE::MovieScene::FDecompositionQuery& InQuery, double InCurrentValue); /** * Recompose a value from the constituent parts specified in InQuery, taking into account the weightings of each channel. * For instance, if a property comprises 3 additive values (a:1, b:2, c:3), and we recompose 'a' with an InCurrentValue of 10, the result for a would be 5. * @note: ValueType must be either copy assignable to/from the storage type of the property, or must have a ConvertOperationalProperty overload * * @param InComponents The components that define the property to decompose * @param InQuery The query defining the entities and object to recompose * @param InCurrentValue The value of the property to recompose * @return A result matching the storage type of the components, containing recomposed values for each of the entities specified in InQuery */ template UE::MovieScene::TRecompositionResult RecomposeBlend(const UE::MovieScene::TPropertyComponents& InComponents, const UE::MovieScene::FDecompositionQuery& InQuery, const ValueType& InCurrentValue) { typename PropertyTraits::StorageType WorkingValue{}; ConvertOperationalProperty(InCurrentValue, WorkingValue); WorkingValue = RecomposeBlendOperational(InComponents, InQuery, WorkingValue); ValueType Result{}; ConvertOperationalProperty(WorkingValue, Result); return Result; } /** * Recompose a value from the constituent parts specified in InQuery, taking into account the weightings of each channel. * For instance, if a property comprises 3 additive values (a:1, b:2, c:3), and we recompose 'a' with an InCurrentValue of 10, the result for a would be 5. * * @param InComponents The components that define the property to decompose * @param InQuery The query defining the entities and object to recompose * @param InCurrentValue The value of the property to recompose * @return A result matching the storage type of the components, containing recomposed values for each of the entities specified in InQuery */ template UE::MovieScene::TRecompositionResult RecomposeBlendOperational(const UE::MovieScene::TPropertyComponents& InComponents, const UE::MovieScene::FDecompositionQuery& InQuery, const typename PropertyTraits::StorageType& InCurrentValue); public: struct FPropertyInfo { FPropertyInfo() : BlendChannel(INVALID_BLEND_CHANNEL) {} /** POinter to the blender system to use for this property, if its blended */ TWeakObjectPtr Blender; UE::MovieScene::FInterrogationChannel InterrogationChannel; /** The entity that contains the property component itself. For fast path properties this is the actual child entity produced from the bound object instantiators. */ UE::MovieScene::FMovieSceneEntityID PropertyEntityID; /** Blend channel allocated from Blender, or INVALID_BLEND_CHANNEL if unblended. */ uint16 BlendChannel; }; // TOverlappingEntityTracker handler interface MOVIESCENETRACKS_API void InitializeOutput(UE::MovieScene::FInterrogationKey Key, TArrayView Inputs, FPropertyInfo* Output, UE::MovieScene::FEntityOutputAggregate Aggregate); MOVIESCENETRACKS_API void UpdateOutput(UE::MovieScene::FInterrogationKey Key, TArrayView Inputs, FPropertyInfo* Output, UE::MovieScene::FEntityOutputAggregate Aggregate); MOVIESCENETRACKS_API void DestroyOutput(UE::MovieScene::FInterrogationKey Key, FPropertyInfo* Output, UE::MovieScene::FEntityOutputAggregate Aggregate); const FPropertyInfo* FindPropertyInfo(UE::MovieScene::FInterrogationKey Key) const { return PropertyTracker.FindOutput(Key); } void FindEntityIDs(UE::MovieScene::FInterrogationKey Key, TArray& OutEntityIDs) const { PropertyTracker.FindEntityIDs(Key, OutEntityIDs); } private: MOVIESCENETRACKS_API virtual void OnRun(FSystemTaskPrerequisites& InPrerequisites, FSystemSubsequentTasks& Subsequents) override; MOVIESCENETRACKS_API virtual bool IsRelevantImpl(UMovieSceneEntitySystemLinker* InLinker) const override; MOVIESCENETRACKS_API bool PropertySupportsFastPath(TArrayView Inputs, FPropertyInfo* Output) const; MOVIESCENETRACKS_API UClass* ResolveBlenderClass(const UE::MovieScene::FPropertyDefinition& PropertyDefinition, TArrayView Inputs) const; MOVIESCENETRACKS_API UE::MovieScene::FPropertyRecomposerPropertyInfo FindPropertyFromSource(FMovieSceneEntityID EntityID, UObject* Object) const; private: static constexpr uint16 INVALID_BLEND_CHANNEL = uint16(-1); UE::MovieScene::TOverlappingEntityTracker PropertyTracker; UE::MovieScene::FComponentMask CleanFastPathMask; UE::MovieScene::FBuiltInComponentTypes* BuiltInComponents; UE::MovieScene::FPropertyRecomposerImpl RecomposerImpl; }; template UE::MovieScene::TRecompositionResult UMovieSceneInterrogatedPropertyInstantiatorSystem::RecomposeBlendOperational(const UE::MovieScene::TPropertyComponents& Components, const UE::MovieScene::FDecompositionQuery& InQuery, const typename PropertyTraits::StorageType& InCurrentValue) { return RecomposerImpl.RecomposeBlendOperational(Components, InQuery, InCurrentValue); }