Sequencer: Large world coordinates support

- Add support for double precision channels, curves, evaluation, blending, and all other runtime infrastructure.
- Note that, as usual for now, double channels load and save float values.
- Editor side also gains some new track editors for these new types, with some workarounds to correctly recognize between float and double vectors.
- Transform tracks are now operating entirely in doubles.
- Float recomposing APIs for keying tracks in the editor are now using doubles, and have been renamed to "value recomposing".

#rb max.chen
#preflight 6123f6d9e7a3070001ff37ed

#ROBOMERGE-SOURCE: CL 17278174 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v858-17259218)

[CL 17278198 by ludovic chabant in ue5-release-engine-test branch]
This commit is contained in:
ludovic chabant
2021-08-23 18:26:59 -04:00
parent 770bb28a7b
commit 92075f84a6
114 changed files with 7880 additions and 3638 deletions
@@ -78,16 +78,16 @@ void FMovieScene3DTransformSectionRecorder::CreateSection(UObject* InObjectToRec
FVector EulerRotation = DefaultTransform.GetRotation().Rotator().Euler();
FVector Scale = DefaultTransform.GetScale3D();
TArrayView<FMovieSceneFloatChannel*> FloatChannels = MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
FloatChannels[0]->SetDefault(Translation.X);
FloatChannels[1]->SetDefault(Translation.Y);
FloatChannels[2]->SetDefault(Translation.Z);
FloatChannels[3]->SetDefault(EulerRotation.X);
FloatChannels[4]->SetDefault(EulerRotation.Y);
FloatChannels[5]->SetDefault(EulerRotation.Z);
FloatChannels[6]->SetDefault(Scale.X);
FloatChannels[7]->SetDefault(Scale.Y);
FloatChannels[8]->SetDefault(Scale.Z);
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
DoubleChannels[0]->SetDefault(Translation.X);
DoubleChannels[1]->SetDefault(Translation.Y);
DoubleChannels[2]->SetDefault(Translation.Z);
DoubleChannels[3]->SetDefault(EulerRotation.X);
DoubleChannels[4]->SetDefault(EulerRotation.Y);
DoubleChannels[5]->SetDefault(EulerRotation.Z);
DoubleChannels[6]->SetDefault(Scale.X);
DoubleChannels[7]->SetDefault(Scale.Y);
DoubleChannels[8]->SetDefault(Scale.Z);
FFrameRate TickResolution = MovieSceneSection->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber CurrentFrame = (Time * TickResolution).FloorToFrame();
@@ -229,51 +229,51 @@ void FMovieScene3DTransformSectionRecorder::FinalizeSection(float CurrentTime)
const ERichCurveInterpMode Interpolation = AnimRecorder.IsValid() ? RCIM_Linear : RCIM_Cubic;
// add buffered transforms
TArrayView<FMovieSceneFloatChannel*> FloatChannels = MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
auto Transformation = [Interpolation](float In)
auto Transformation = [Interpolation](double In)
{
FMovieSceneFloatValue NewValue(In);
FMovieSceneDoubleValue NewValue(In);
NewValue.InterpMode = Interpolation;
return NewValue;
};
TArray<FMovieSceneFloatValue> FloatValues;
TArray<FMovieSceneDoubleValue> DoubleValues;
FloatValues.Reset(BufferedTransforms.LocationX.Num());
Algo::Transform(BufferedTransforms.LocationX, FloatValues, Transformation);
FloatChannels[0]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.LocationX.Num());
Algo::Transform(BufferedTransforms.LocationX, DoubleValues, Transformation);
DoubleChannels[0]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.LocationY.Num());
Algo::Transform(BufferedTransforms.LocationY, FloatValues, Transformation);
FloatChannels[1]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.LocationY.Num());
Algo::Transform(BufferedTransforms.LocationY, DoubleValues, Transformation);
DoubleChannels[1]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.LocationZ.Num());
Algo::Transform(BufferedTransforms.LocationZ, FloatValues, Transformation);
FloatChannels[2]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.LocationZ.Num());
Algo::Transform(BufferedTransforms.LocationZ, DoubleValues, Transformation);
DoubleChannels[2]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.RotationX.Num());
Algo::Transform(BufferedTransforms.RotationX, FloatValues, Transformation);
FloatChannels[3]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.RotationX.Num());
Algo::Transform(BufferedTransforms.RotationX, DoubleValues, Transformation);
DoubleChannels[3]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.RotationY.Num());
Algo::Transform(BufferedTransforms.RotationY, FloatValues, Transformation);
FloatChannels[4]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.RotationY.Num());
Algo::Transform(BufferedTransforms.RotationY, DoubleValues, Transformation);
DoubleChannels[4]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.RotationZ.Num());
Algo::Transform(BufferedTransforms.RotationZ, FloatValues, Transformation);
FloatChannels[5]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.RotationZ.Num());
Algo::Transform(BufferedTransforms.RotationZ, DoubleValues, Transformation);
DoubleChannels[5]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.ScaleX.Num());
Algo::Transform(BufferedTransforms.ScaleX, FloatValues, Transformation);
FloatChannels[6]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.ScaleX.Num());
Algo::Transform(BufferedTransforms.ScaleX, DoubleValues, Transformation);
DoubleChannels[6]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.ScaleY.Num());
Algo::Transform(BufferedTransforms.ScaleY, FloatValues, Transformation);
FloatChannels[7]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.ScaleY.Num());
Algo::Transform(BufferedTransforms.ScaleY, DoubleValues, Transformation);
DoubleChannels[7]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FloatValues.Reset(BufferedTransforms.ScaleZ.Num());
Algo::Transform(BufferedTransforms.ScaleZ, FloatValues, Transformation);
FloatChannels[8]->Set(BufferedTransforms.Times, MoveTemp(FloatValues));
DoubleValues.Reset(BufferedTransforms.ScaleZ.Num());
Algo::Transform(BufferedTransforms.ScaleZ, DoubleValues, Transformation);
DoubleChannels[8]->Set(BufferedTransforms.Times, MoveTemp(DoubleValues));
FTransform FirstTransform = FTransform::Identity;
if (BufferedTransforms.Times.Num())
@@ -293,14 +293,14 @@ void FMovieScene3DTransformSectionRecorder::FinalizeSection(float CurrentTime)
{
FKeyDataOptimizationParams Params;
for (FMovieSceneFloatChannel* Channel : FloatChannels)
for (FMovieSceneDoubleChannel* Channel : DoubleChannels)
{
Channel->Optimize(Params);
}
}
else
{
for (FMovieSceneFloatChannel* Channel : FloatChannels)
for (FMovieSceneDoubleChannel* Channel : DoubleChannels)
{
Channel->AutoSetTangents();
}
@@ -311,14 +311,14 @@ void FMovieScene3DTransformSectionRecorder::FinalizeSection(float CurrentTime)
if(!bWasAttached)
{
bool bCanRemoveTrack = true;
for (FMovieSceneFloatChannel* Channel : MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>())
for (FMovieSceneDoubleChannel* Channel : MovieSceneSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>())
{
if (Channel)
{
int32 NumKeys = Channel->GetTimes().Num();
if (NumKeys == 1)
{
*Channel = FMovieSceneFloatChannel();
*Channel = FMovieSceneDoubleChannel();
}
else if (NumKeys > 1)
{
@@ -8,6 +8,8 @@
#include "Tracks/MovieSceneByteTrack.h"
#include "Sections/MovieSceneEnumSection.h"
#include "Tracks/MovieSceneEnumTrack.h"
#include "Sections/MovieSceneDoubleSection.h"
#include "Tracks/MovieSceneDoubleTrack.h"
#include "Sections/MovieSceneFloatSection.h"
#include "Tracks/MovieSceneFloatTrack.h"
#include "Sections/MovieSceneColorSection.h"
@@ -347,13 +349,13 @@ void FMovieScenePropertyRecorder<FColor>::ReduceKeys(UMovieSceneSection* InSecti
}
template <>
bool FMovieScenePropertyRecorder<FVector>::ShouldAddNewKey(const FVector& InNewValue) const
bool FMovieScenePropertyRecorder<FVector3f>::ShouldAddNewKey(const FVector3f& InNewValue) const
{
return true;
}
template <>
UMovieSceneSection* FMovieScenePropertyRecorder<FVector>::AddSection(UObject* InObjectToRecord, UMovieScene* InMovieScene, const FGuid& InGuid, float InTime)
UMovieSceneSection* FMovieScenePropertyRecorder<FVector3f>::AddSection(UObject* InObjectToRecord, UMovieScene* InMovieScene, const FGuid& InGuid, float InTime)
{
if (!InObjectToRecord)
{
@@ -361,10 +363,10 @@ UMovieSceneSection* FMovieScenePropertyRecorder<FVector>::AddSection(UObject* In
}
FName TrackName = *Binding.GetPropertyPath();
UMovieSceneVectorTrack* Track = InMovieScene->FindTrack<UMovieSceneVectorTrack>(InGuid, TrackName);
UMovieSceneFloatVectorTrack* Track = InMovieScene->FindTrack<UMovieSceneFloatVectorTrack>(InGuid, TrackName);
if (!Track)
{
Track = InMovieScene->AddTrack<UMovieSceneVectorTrack>(InGuid);
Track = InMovieScene->AddTrack<UMovieSceneFloatVectorTrack>(InGuid);
}
else
{
@@ -376,7 +378,7 @@ UMovieSceneSection* FMovieScenePropertyRecorder<FVector>::AddSection(UObject* In
Track->SetNumChannelsUsed(3);
Track->SetPropertyNameAndPath(Binding.GetPropertyName(), Binding.GetPropertyPath());
UMovieSceneVectorSection* Section = Cast<UMovieSceneVectorSection>(Track->CreateNewSection());
UMovieSceneFloatVectorSection* Section = Cast<UMovieSceneFloatVectorSection>(Track->CreateNewSection());
FFrameRate TickResolution = Section->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber CurrentFrame = (InTime * TickResolution).FloorToFrame();
@@ -405,7 +407,7 @@ UMovieSceneSection* FMovieScenePropertyRecorder<FVector>::AddSection(UObject* In
}
template <>
void FMovieScenePropertyRecorder<FVector>::AddKeyToSection(UMovieSceneSection* InSection, const FPropertyKey<FVector>& InKey)
void FMovieScenePropertyRecorder<FVector3f>::AddKeyToSection(UMovieSceneSection* InSection, const FPropertyKey<FVector3f>& InKey)
{
TArrayView<FMovieSceneFloatChannel*> FloatChannels = InSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
FloatChannels[0]->AddCubicKey(InKey.Time, InKey.Value.X);
@@ -414,7 +416,7 @@ void FMovieScenePropertyRecorder<FVector>::AddKeyToSection(UMovieSceneSection* I
}
template <>
void FMovieScenePropertyRecorder<FVector>::ReduceKeys(UMovieSceneSection* InSection)
void FMovieScenePropertyRecorder<FVector3f>::ReduceKeys(UMovieSceneSection* InSection)
{
TArrayView<FMovieSceneFloatChannel*> FloatChannels = InSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
@@ -424,8 +426,87 @@ void FMovieScenePropertyRecorder<FVector>::ReduceKeys(UMovieSceneSection* InSect
UE::MovieScene::Optimize(FloatChannels[2], Params);
}
template <>
bool FMovieScenePropertyRecorder<FVector3d>::ShouldAddNewKey(const FVector3d& InNewValue) const
{
return true;
}
template <>
UMovieSceneSection* FMovieScenePropertyRecorder<FVector3d>::AddSection(UObject* InObjectToRecord, UMovieScene* InMovieScene, const FGuid& InGuid, float InTime)
{
if (!InObjectToRecord)
{
return nullptr;
}
FName TrackName = *Binding.GetPropertyPath();
UMovieSceneDoubleVectorTrack* Track = InMovieScene->FindTrack<UMovieSceneDoubleVectorTrack>(InGuid, TrackName);
if (!Track)
{
Track = InMovieScene->AddTrack<UMovieSceneDoubleVectorTrack>(InGuid);
}
else
{
Track->RemoveAllAnimationData();
}
if (Track)
{
Track->SetNumChannelsUsed(3);
Track->SetPropertyNameAndPath(Binding.GetPropertyName(), Binding.GetPropertyPath());
UMovieSceneDoubleVectorSection* Section = Cast<UMovieSceneDoubleVectorSection>(Track->CreateNewSection());
FFrameRate TickResolution = Section->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber CurrentFrame = (InTime * TickResolution).FloorToFrame();
Section->SetRange(TRange<FFrameNumber>::Inclusive(CurrentFrame, CurrentFrame));
Section->TimecodeSource = SequenceRecorderUtils::GetTimecodeSource();
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = Section->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
DoubleChannels[0]->SetDefault(PreviousValue.X);
DoubleChannels[0]->AddCubicKey(CurrentFrame, PreviousValue.X, RCTM_Break);
DoubleChannels[1]->SetDefault(PreviousValue.Y);
DoubleChannels[1]->AddCubicKey(CurrentFrame, PreviousValue.Y, RCTM_Break);
DoubleChannels[2]->SetDefault(PreviousValue.Z);
DoubleChannels[2]->AddCubicKey(CurrentFrame, PreviousValue.Z, RCTM_Break);
Track->AddSection(*Section);
return Section;
}
return nullptr;
}
template <>
void FMovieScenePropertyRecorder<FVector3d>::AddKeyToSection(UMovieSceneSection* InSection, const FPropertyKey<FVector3d>& InKey)
{
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = InSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
DoubleChannels[0]->AddCubicKey(InKey.Time, InKey.Value.X);
DoubleChannels[1]->AddCubicKey(InKey.Time, InKey.Value.Y);
DoubleChannels[2]->AddCubicKey(InKey.Time, InKey.Value.Z);
}
template <>
void FMovieScenePropertyRecorder<FVector3d>::ReduceKeys(UMovieSceneSection* InSection)
{
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = InSection->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
FKeyDataOptimizationParams Params;
UE::MovieScene::Optimize(DoubleChannels[0], Params);
UE::MovieScene::Optimize(DoubleChannels[1], Params);
UE::MovieScene::Optimize(DoubleChannels[2], Params);
}
template class FMovieScenePropertyRecorder<bool>;
template class FMovieScenePropertyRecorder<uint8>;
template class FMovieScenePropertyRecorder<float>;
template class FMovieScenePropertyRecorder<FColor>;
template class FMovieScenePropertyRecorder<FVector>;
template class FMovieScenePropertyRecorder<FVector3f>;
template class FMovieScenePropertyRecorder<FVector3d>;