Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

206 lines
6.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Evaluation/Blending/MovieSceneBlendType.h"
#include "Misc/InlineValue.h"
#include "Evaluation/MovieScenePlayback.h"
#include "Evaluation/MovieSceneEvaluationScope.h"
template<typename DataType> struct TMovieSceneInitialValueStore;
/**
* Implementation of custom blend logic should be as follows (using doubles as an example).
* Specializing TBlendableTokenTraits for a particular input data type causes WorkingDataType to be used during the blending operation.
* Where WorkingDataType belongs to a namespace, ADL will be employed to discover any relevant overloads for BlendValue that match the necessary types.
* This allows blending of any arbitrary type into the WorkingDataType.
namespace MovieScene
{
// Define a custom namespaced type that will be used to calculate blends between doubles
struct FBlendableDouble
{
FBlendableDouble()
: AbsoluteTotal(0.0), AdditiveTotal(0.0)
{}
double AbsoluteTotal;
double AdditiveTotal;
TOptional<float> TotalWeight;
double Resolve(TMovieSceneInitialValueStore<int32>& InitialValueStore)
{
if (TotalWeight.IsSet())
{
if (TotalWeight.GetValue() == 0.f)
{
AbsoluteTotal = InitialValueStore.GetInitialValue();
}
else
{
AbsoluteTotal /= TotalWeight.GetValue();
}
}
return AbsoluteTotal + AdditiveTotal;
}
};
void BlendValue(FBlendableDouble& OutBlend, double InValue, float Weight, EMovieSceneBlendType BlendType, TMovieSceneInitialValueStore<double>& InitialValueStore)
{
if (BlendType == EMovieSceneBlendType::Absolute || BlendType == EMovieSceneBlendType::Relative)
{
if (BlendType == EMovieSceneBlendType::Relative)
{
OutBlend.AbsoluteTotal += (InitialValueStore.GetInitialValue() + InValue) * Weight;
}
else
{
OutBlend.AbsoluteTotal += InValue * Weight;
}
OutBlend.TotalWeight = OutBlend.TotalWeight.Get(0.f) + Weight;
}
else if (BlendType == EMovieSceneBlendType::Additive)
{
OutBlend.AdditiveTotal += InValue * Weight;
}
}
}
template<> struct TBlendableTokenTraits<double> { typedef UE::MovieScene::FBlendableDouble WorkingDataType; };
*/
namespace UE
{
namespace MovieScene
{
template<typename InType, typename WorkingDataType, typename SourceDataType>
void BlendValue(WorkingDataType& OutBlend, InType InValue, float Weight, EMovieSceneBlendType BlendType, TMovieSceneInitialValueStore<SourceDataType>& InitialValueStore)
{
BlendValue(OutBlend, InValue, Weight, BlendType, INDEX_NONE, InitialValueStore);
}
//new optional blending priority that supports blending priorities
template<typename InType, typename WorkingDataType, typename SourceDataType>
void BlendValue(WorkingDataType& OutBlend, InType InValue, float Weight, EMovieSceneBlendType BlendType, int32 BlendingOrder, TMovieSceneInitialValueStore<SourceDataType>& InitialValueStore)
{
}
} // namespace MovieScene
} // namespace UE
template<typename DataType> struct TBlendableTokenTraits { typedef DataType WorkingDataType; };
/**
* Templated structure that encapsulates any blendable data type, and the information required to blend it
*/
template<typename DataType>
struct TBlendableToken
{
typedef typename TBlendableTokenTraits<DataType>::WorkingDataType WorkingDataType;
/** Default construction */
TBlendableToken() = default;
/** Construction from a value, blend method, and a weight. Scope and bias to be populated later */
template<typename T>
TBlendableToken(T&& InValue, EMovieSceneBlendType InBlendType, float InWeight = 1.f, int32 InBlendingOrder = INDEX_NONE)
: Value(TData<typename TDecay<T>::Type>(Forward<T>(InValue)))
, HierarchicalBias(0)
, Weight(InWeight)
, BlendType(InBlendType)
, BlendingOrder(InBlendingOrder)
{}
/** Construction from a value, scope, context, blend method, and a weight */
template<typename T>
TBlendableToken(T&& InValue, const FMovieSceneEvaluationScope& InCurrentScope, const FMovieSceneContext& InContext, EMovieSceneBlendType InBlendType, float InWeight = 1.f,
int32 InBlendingOrder = INDEX_NONE)
: Value(TData<typename TDecay<T>::Type>(Forward<T>(InValue)))
, AnimatingScope(InCurrentScope)
, HierarchicalBias(InContext.GetHierarchicalBias())
, Weight(InWeight)
, BlendType(InBlendType)
, BlendingOrder(InBlendingOrder)
{}
/** Copying is disabled */
TBlendableToken(const TBlendableToken&) = delete;
TBlendableToken& operator=(const TBlendableToken&) = delete;
/** Move construction/assignment */
TBlendableToken(TBlendableToken&&) = default;
TBlendableToken& operator=(TBlendableToken&&) = default;
/**
* Add this value into the specified cumulative blend
*
* @param CumulativeBlend The working structure to add our value onto
*/
void AddTo(WorkingDataType& CumulativeBlend, TMovieSceneInitialValueStore<DataType>& InitialValueStore) const
{
check(Value.IsValid());
Value->AddTo(CumulativeBlend, Weight, BlendType, BlendingOrder, InitialValueStore);
}
bool operator<(const TBlendableToken& RHS) const
{
return BlendingOrder < RHS.BlendingOrder;
}
private:
/** Base class for all value types */
struct IData
{
virtual ~IData() {}
virtual void AddTo(WorkingDataType& CumulativeBlend, float Weight, EMovieSceneBlendType BlendType, int32 BlendingOrder, TMovieSceneInitialValueStore<DataType>& InitialValueStore) const = 0;
};
/** Templated value data for any other type */
template<typename T>
struct TData : IData
{
TData(T In) : Data(MoveTemp(In)) {}
virtual void AddTo(WorkingDataType& CumulativeBlend, float InWeight, EMovieSceneBlendType InBlendType, int32 InBlendingOrder, TMovieSceneInitialValueStore<DataType>& InitialValueStore) const
{
// Use the default BlendValue function, or any other BlendValue function found through ADL on WorkingDataType
using UE::MovieScene::BlendValue;
if (InBlendingOrder == INDEX_NONE)
{
BlendValue(CumulativeBlend, Data, InWeight, InBlendType, InitialValueStore);
}
else
{
BlendValue(CumulativeBlend, Data, InWeight, InBlendType, InBlendingOrder, InitialValueStore);
}
}
/** The actual value to blend */
T Data;
};
/** The actual user provided value data, stored as inline bytes (unless it's > sizeof(DataType)) */
TInlineValue<IData, sizeof(DataType)> Value;
public:
/** The scope from which this token was generated. Used for restoring pre-animated state where necessary. */
FMovieSceneEvaluationScope AnimatingScope;
/** The hierarchical bias for this template instance */
int32 HierarchicalBias;
/** Weight to apply to the value */
float Weight;
/** Enumeration specifying how this token should be blended */
EMovieSceneBlendType BlendType;
/** Opitonal Blending Order, if present will be used to sort additives and override blend types*/
int32 BlendingOrder = INDEX_NONE;
};