// Copyright Epic Games, Inc. All Rights Reserved. #include "Channels/FloatChannelCurveModel.h" #include "Channels/CurveModelHelpers.h" #include "Channels/FloatChannelKeyProxy.h" #include "Channels/MovieSceneChannelData.h" #include "Channels/MovieSceneChannelHandle.h" #include "Channels/MovieSceneFloatChannel.h" #include "Containers/Array.h" #include "Containers/UnrealString.h" #include "CurveDataAbstraction.h" #include "CurveEditorScreenSpace.h" #include "Curves/KeyHandle.h" #include "IBufferedCurveModel.h" #include "Internationalization/Text.h" #include "Math/Range.h" #include "Math/UnrealMathSSE.h" #include "Misc/FrameNumber.h" #include "Misc/FrameRate.h" #include "MovieScene.h" #include "MovieSceneSection.h" #include "Templates/Casts.h" #include "Templates/Tuple.h" #include "Templates/UnrealTemplate.h" #include "UObject/Package.h" #include "UObject/UObjectGlobals.h" #include "UObject/UnrealNames.h" #include "UObject/WeakObjectPtr.h" #include "UObject/WeakObjectPtrTemplates.h" class FCurveEditor; class ISequencer; class UObject; /** * Buffered curve implementation for a float channel curve model, stores a copy of the float channel in order to draw itself. */ class FFloatChannelBufferedCurveModel : public IBufferedCurveModel { public: /** Create a copy of the float channel while keeping the reference to the section */ FFloatChannelBufferedCurveModel(const FMovieSceneFloatChannel* InMovieSceneFloatChannel, TWeakObjectPtr InWeakSection, TArray&& InKeyPositions, TArray&& InKeyAttributes, const FString& InLongDisplayName, const double InValueMin, const double InValueMax) : IBufferedCurveModel(MoveTemp(InKeyPositions), MoveTemp(InKeyAttributes), InLongDisplayName, InValueMin, InValueMax) , Channel(*InMovieSceneFloatChannel) , WeakSection(InWeakSection) {} virtual void DrawCurve(const FCurveEditor& InCurveEditor, const FCurveEditorScreenSpace& InScreenSpace, TArray>& OutInterpolatingPoints) const override { UMovieSceneSection* Section = WeakSection.Get(); if (Section && Section->GetTypedOuter()) { FFrameRate TickResolution = Section->GetTypedOuter()->GetTickResolution(); const double StartTimeSeconds = InScreenSpace.GetInputMin(); const double EndTimeSeconds = InScreenSpace.GetInputMax(); const double TimeThreshold = FMath::Max(0.0001, 1.0 / InScreenSpace.PixelsPerInput()); const double ValueThreshold = FMath::Max(0.0001, 1.0 / InScreenSpace.PixelsPerOutput()); Channel.PopulateCurvePoints(StartTimeSeconds, EndTimeSeconds, TimeThreshold, ValueThreshold, TickResolution, OutInterpolatingPoints); } } virtual bool Evaluate(double InTime, double& OutValue) const override { return UE::MovieSceneTools::CurveHelpers::Evaluate(InTime, OutValue, Channel, WeakSection); } private: FMovieSceneFloatChannel Channel; TWeakObjectPtr WeakSection; }; FFloatChannelCurveModel::FFloatChannelCurveModel(TMovieSceneChannelHandle InChannel, UMovieSceneSection* OwningSection, TWeakPtr InWeakSequencer) : FBezierChannelCurveModel(InChannel, OwningSection, InWeakSequencer) { } void FFloatChannelCurveModel::CreateKeyProxies(TArrayView InKeyHandles, TArrayView OutObjects) { for (int32 Index = 0; Index < InKeyHandles.Num(); ++Index) { UFloatChannelKeyProxy* NewProxy = NewObject(GetTransientPackage(), NAME_None); NewProxy->Initialize(InKeyHandles[Index], GetChannelHandle(), this->GetOwningObjectOrOuter()); OutObjects[Index] = NewProxy; } } TUniquePtr FFloatChannelCurveModel::CreateBufferedCurveCopy() const { FMovieSceneFloatChannel* Channel = GetChannelHandle().Get(); if (Channel) { TArray TargetKeyHandles; TMovieSceneChannelData ChannelData = Channel->GetData(); TRange TotalRange = ChannelData.GetTotalRange(); ChannelData.GetKeys(TotalRange, nullptr, &TargetKeyHandles); TArray KeyPositions; KeyPositions.SetNumUninitialized(GetNumKeys()); TArray KeyAttributes; KeyAttributes.SetNumUninitialized(GetNumKeys()); GetKeyPositions(TargetKeyHandles, KeyPositions); GetKeyAttributes(TargetKeyHandles, KeyAttributes); double ValueMin = 0.f, ValueMax = 1.f; GetValueRange(ValueMin, ValueMax); return MakeUnique(Channel, this->GetOwningObjectOrOuter(), MoveTemp(KeyPositions), MoveTemp(KeyAttributes), GetLongDisplayName().ToString(), ValueMin, ValueMax); } return nullptr; }