// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Channels/MovieSceneChannelEditorData.h" #include "Containers/Array.h" #include "Containers/ArrayView.h" #include "HAL/Platform.h" #include "HAL/PlatformCrt.h" #include "Math/Range.h" #include "Misc/AssertionMacros.h" #include "Misc/FrameNumber.h" #include "Misc/FrameTime.h" #include "Misc/Optional.h" #include "MovieSceneChannel.h" #include "MovieSceneChannelData.h" #include "MovieSceneChannelTraits.h" #include "Serialization/StructuredArchive.h" #include "Templates/UnrealTemplate.h" #include "UObject/Class.h" #include "UObject/ObjectMacros.h" #include "Curves/RealCurve.h" #include "MovieSceneIntegerChannel.generated.h" struct FFrameRate; struct FKeyHandle; struct FPropertyTag; USTRUCT() struct FMovieSceneIntegerChannel : public FMovieSceneChannel { GENERATED_BODY() typedef int32 CurveValueType; FMovieSceneIntegerChannel() : PreInfinityExtrap(RCCE_Constant) , PostInfinityExtrap(RCCE_Constant) , bInterpolateLinearKeys(false) , DefaultValue(0) , bHasDefaultValue(false) {} /** * Serialize this type from another */ MOVIESCENE_API bool SerializeFromMismatchedTag(const FPropertyTag& Tag, FStructuredArchive::FSlot Slot); /** * Access a mutable interface for this channel's data * * @return An object that is able to manipulate this channel's data */ FORCEINLINE TMovieSceneChannelData GetData() { return TMovieSceneChannelData(&Times, &Values, this, &KeyHandles); } /** * Access a constant interface for this channel's data * * @return An object that is able to interrogate this channel's data */ FORCEINLINE TMovieSceneChannelData GetData() const { return TMovieSceneChannelData(&Times, &Values); } /** * Const access to this channel's times */ FORCEINLINE TArrayView GetTimes() const { return Times; } /** * Const access to this channel's values */ FORCEINLINE TArrayView GetValues() const { return Values; } /** * Check whether this channel has any data */ FORCEINLINE bool HasAnyData() const { return Times.Num() != 0 || bHasDefaultValue == true; } /** * Evaluate this channel * * @param InTime The time to evaluate at * @param OutValue A value to receive the result * @return true if the channel was evaluated successfully, false otherwise */ MOVIESCENE_API bool Evaluate(FFrameTime InTime, int32& OutValue) const; /** * Evaluate the interpolated value when bInterpolateLinearKeys is true * * @param InTime The time to evaluate at * @param OutValue A value to receive the result * @return true if the channel was evaluated successfully, false otherwise */ MOVIESCENE_API bool EvaluateInterp(FFrameTime InTime, double& OutValue) const; /** * Set the channel's times and values to the requested values */ FORCEINLINE void Set(TArray InTimes, TArray InValues) { check(InTimes.Num() == InValues.Num()); Times = MoveTemp(InTimes); Values = MoveTemp(InValues); KeyHandles.Reset(); for (int32 Index = 0; Index < Times.Num(); ++Index) { KeyHandles.AllocateHandle(Index); } } /** * Add keys with these times to channel. The number of elements in both arrays much match or nothing is added. * @param InTimes Times to add * @param InValues Values to add */ FORCEINLINE void AddKeys(const TArray& InTimes, const TArray& InValues) { check(InTimes.Num() == InValues.Num()); int32 Index = Times.Num(); Times.Append(InTimes); Values.Append(InValues); for (; Index < Times.Num(); ++Index) { KeyHandles.AllocateHandle(Index); } } public: // ~ FMovieSceneChannel Interface MOVIESCENE_API virtual void GetKeys(const TRange& WithinRange, TArray* OutKeyTimes, TArray* OutKeyHandles) override; MOVIESCENE_API virtual void GetKeyTimes(TArrayView InHandles, TArrayView OutKeyTimes) override; MOVIESCENE_API virtual void SetKeyTimes(TArrayView InHandles, TArrayView InKeyTimes) override; MOVIESCENE_API virtual void DuplicateKeys(TArrayView InHandles, TArrayView OutNewHandles) override; MOVIESCENE_API virtual void DeleteKeys(TArrayView InHandles) override; MOVIESCENE_API virtual void DeleteKeysFrom(FFrameNumber InTime, bool bDeleteKeysBefore) override; MOVIESCENE_API virtual void RemapTimes(const UE::MovieScene::IRetimingInterface& Retimer) override; MOVIESCENE_API virtual TRange ComputeEffectiveRange() const override; MOVIESCENE_API virtual int32 GetNumKeys() const override; MOVIESCENE_API virtual void Reset() override; MOVIESCENE_API virtual void Offset(FFrameNumber DeltaPosition) override; MOVIESCENE_API virtual void Optimize(const FKeyDataOptimizationParams& InParameters) override; MOVIESCENE_API virtual void ClearDefault() override; MOVIESCENE_API virtual FKeyHandle GetHandle(int32 Index) override; MOVIESCENE_API virtual int32 GetIndex(FKeyHandle Handle) override; public: /** * Set this channel's default value that should be used when no keys are present * * @param InDefaultValue The desired default value */ FORCEINLINE void SetDefault(int32 InDefaultValue) { bHasDefaultValue = true; DefaultValue = InDefaultValue; } /** * Get this channel's default value that will be used when no keys are present * * @return (Optional) The channel's default value */ FORCEINLINE TOptional GetDefault() const { return bHasDefaultValue ? TOptional(DefaultValue) : TOptional(); } /** * Remove this channel's default value causing the channel to have no effect where no keys are present */ FORCEINLINE void RemoveDefault() { bHasDefaultValue = false; } public: /** Pre-infinity extrapolation state, integer channel supports them all but linear since that requires a tangent*/ UPROPERTY() TEnumAsByte PreInfinityExtrap; /** Post-infinity extrapolation state, integer channel supports them all but linear since that requires a tangent*/ UPROPERTY() TEnumAsByte PostInfinityExtrap; /** Whether to evaluate linear keys as interpolated or not*/ UPROPERTY() bool bInterpolateLinearKeys; private: UPROPERTY(meta=(KeyTimes)) TArray Times; UPROPERTY() int32 DefaultValue; UPROPERTY() bool bHasDefaultValue; UPROPERTY(meta=(KeyValues)) TArray Values; /** This needs to be a UPROPERTY so it gets saved into editor transactions but transient so it doesn't get saved into assets. */ UPROPERTY(Transient) FMovieSceneKeyHandleMap KeyHandles; }; template<> struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 { enum { WithStructuredSerializeFromMismatchedTag = true }; }; template<> struct TMovieSceneChannelTraits : TMovieSceneChannelTraitsBase { #if WITH_EDITOR /** Integer channels can have external values (ie, they can get their values from external objects for UI purposes) */ typedef TMovieSceneExternalValue ExtendedEditorDataType; #endif };