// Copyright Epic Games, Inc. All Rights Reserved. #include "Channels/BoolChannelCurveModel.h" #include "Math/Vector2D.h" #include "HAL/PlatformMath.h" #include "Channels/MovieSceneBoolChannel.h" #include "Channels/BoolChannelKeyProxy.h" #include "MovieSceneSection.h" #include "MovieScene.h" #include "CurveDrawInfo.h" #include "CurveDataAbstraction.h" #include "CurveEditor.h" #include "CurveEditorScreenSpace.h" #include "CurveEditorSnapMetrics.h" #include "Styling/AppStyle.h" #include "BuiltInChannelEditors.h" #include "SequencerChannelTraits.h" #include "ISequencer.h" #include "Channels/MovieSceneChannelProxy.h" /** * Buffered curve implementation for a bool channel curve model, stores a copy of the bool channel in order to draw itself. */ class FBoolChannelBufferedCurveModel : public IBufferedCurveModel { public: /** Create a copy of the float channel while keeping the reference to the section */ FBoolChannelBufferedCurveModel(const FMovieSceneBoolChannel* InMovieSceneBoolChannel, TWeakObjectPtr InWeakSection, TArray&& InKeyPositions, TArray&& InKeyAttributes, const FString& InLongDisplayName, const double InValueMin, const double InValueMax) : IBufferedCurveModel(MoveTemp(InKeyPositions), MoveTemp(InKeyAttributes), InLongDisplayName, InValueMin, InValueMax) , Channel(*InMovieSceneBoolChannel) , WeakSection(InWeakSection) {} virtual void DrawCurve(const FCurveEditor& InCurveEditor, const FCurveEditorScreenSpace& InScreenSpace, TArray>& OutInterpolatingPoints) const override { UMovieSceneSection* Section = WeakSection.Get(); if (Section) { FFrameRate TickResolution = Section->GetTypedOuter()->GetTickResolution(); TMovieSceneChannelData ChannelData = Channel.GetData(); TArrayView Times = ChannelData.GetTimes(); TArrayView Values = ChannelData.GetValues(); const double StartTimeSeconds = InScreenSpace.GetInputMin(); const double EndTimeSeconds = InScreenSpace.GetInputMax(); const FFrameNumber StartFrame = (StartTimeSeconds * TickResolution).FloorToFrame(); const FFrameNumber EndFrame = (EndTimeSeconds * TickResolution).CeilToFrame(); const int32 StartingIndex = Algo::UpperBound(Times, StartFrame); const int32 EndingIndex = Algo::LowerBound(Times, EndFrame); for (int32 KeyIndex = StartingIndex; KeyIndex < EndingIndex; ++KeyIndex) { OutInterpolatingPoints.Add(MakeTuple(Times[KeyIndex] / TickResolution, double(Values[KeyIndex]))); } } } private: FMovieSceneBoolChannel Channel; TWeakObjectPtr WeakSection; }; FBoolChannelCurveModel::FBoolChannelCurveModel(TMovieSceneChannelHandle InChannel, UMovieSceneSection* OwningSection, TWeakPtr InWeakSequencer) : FChannelCurveModel(InChannel, OwningSection, InWeakSequencer) { } void FBoolChannelCurveModel::CreateKeyProxies(TArrayView InKeyHandles, TArrayView OutObjects) { for (int32 Index = 0; Index < InKeyHandles.Num(); ++Index) { UBoolChannelKeyProxy* NewProxy = NewObject(GetTransientPackage(), NAME_None); NewProxy->Initialize(InKeyHandles[Index], GetChannelHandle(), Cast(GetOwningObject())); OutObjects[Index] = NewProxy; } } TUniquePtr FBoolChannelCurveModel::CreateBufferedCurveCopy() const { FMovieSceneBoolChannel* 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, Cast(GetOwningObject()), MoveTemp(KeyPositions), MoveTemp(KeyAttributes), GetLongDisplayName().ToString(), ValueMin, ValueMax); } return nullptr; } double FBoolChannelCurveModel::GetKeyValue(TArrayView Values, int32 Index) const { return (double)Values[Index]; } void FBoolChannelCurveModel::SetKeyValue(int32 Index, double KeyValue) const { FMovieSceneBoolChannel* Channel = GetChannelHandle().Get(); if (Channel) { TMovieSceneChannelData ChannelData = Channel->GetData(); ChannelData.GetValues()[Index] = KeyValue > 0 ? true : false; } }