Files
UnrealEngineUWP/Engine/Source/Editor/MovieSceneTools/Private/MatineeImportTools.cpp
2022-05-26 12:52:45 -04:00

1144 lines
44 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MatineeImportTools.h"
#include "MovieSceneSequence.h"
#include "Tracks/MovieSceneAudioTrack.h"
#include "ScopedTransaction.h"
#include "MovieSceneCommonHelpers.h"
#include "MovieSceneTimeHelpers.h"
#include "IMovieScenePlayer.h"
#include "Channels/MovieSceneChannelProxy.h"
#include "MovieScene.h"
#include "MovieSceneSequenceEditor.h"
#include "Channels/MovieSceneEvent.h"
#include "K2Node_CustomEvent.h"
#include "MovieSceneSequenceEditor.h"
#include "Kismet2/KismetEditorUtilities.h"
#include "MovieSceneEventUtils.h"
#include "Animation/SkeletalMeshActor.h"
#include "EngineUtils.h"
#include "Matinee/MatineeActor.h"
#include "Matinee/InterpData.h"
#include "Matinee/InterpGroupInst.h"
#include "Matinee/InterpTrackFloatMaterialParam.h"
#include "Matinee/InterpTrackVectorMaterialParam.h"
#include "Matinee/InterpTrackLinearColorProp.h"
#include "Matinee/InterpTrackColorProp.h"
#include "Matinee/InterpTrackBoolProp.h"
#include "Matinee/InterpTrackMoveAxis.h"
#include "Matinee/InterpTrackAnimControl.h"
#include "Matinee/InterpTrackSound.h"
#include "Matinee/InterpTrackFade.h"
#include "Matinee/InterpTrackDirector.h"
#include "Matinee/InterpTrackEvent.h"
#include "Matinee/InterpTrackVectorProp.h"
#include "Matinee/InterpTrackVisibility.h"
#include "Matinee/InterpTrackSlomo.h"
#include "Tracks/MovieSceneBoolTrack.h"
#include "Tracks/MovieSceneFloatTrack.h"
#include "Tracks/MovieSceneMaterialTrack.h"
#include "Tracks/MovieSceneColorTrack.h"
#include "Tracks/MovieScene3DTransformTrack.h"
#include "Tracks/MovieSceneParticleTrack.h"
#include "Tracks/MovieSceneSkeletalAnimationTrack.h"
#include "Tracks/MovieSceneFadeTrack.h"
#include "Tracks/MovieSceneCameraCutTrack.h"
#include "Tracks/MovieSceneEventTrack.h"
#include "Tracks/MovieSceneVisibilityTrack.h"
#include "Tracks/MovieSceneAudioTrack.h"
#include "Tracks/MovieSceneVectorTrack.h"
#include "Tracks/MovieSceneSlomoTrack.h"
#include "Sections/MovieSceneColorSection.h"
#include "Sections/MovieSceneBoolSection.h"
#include "Sections/MovieSceneFloatSection.h"
#include "Sections/MovieScene3DTransformSection.h"
#include "Sections/MovieSceneSkeletalAnimationSection.h"
#include "Sections/MovieSceneAudioSection.h"
#include "Sections/MovieSceneFadeSection.h"
#include "Sections/MovieSceneCameraCutSection.h"
#include "Sections/MovieSceneEventSection.h"
#include "Sections/MovieSceneEventTriggerSection.h"
#include "Sections/MovieSceneVectorSection.h"
#include "Sections/MovieSceneParameterSection.h"
#include "Sections/MovieSceneSlomoSection.h"
#include "Animation/AnimSequence.h"
EMatineeImportSectionRangeMode FMatineeImportTools::SectionRangeMode = EMatineeImportSectionRangeMode::All;
ERichCurveInterpMode FMatineeImportTools::MatineeInterpolationToRichCurveInterpolation( EInterpCurveMode CurveMode )
{
switch ( CurveMode )
{
case CIM_Constant:
return ERichCurveInterpMode::RCIM_Constant;
case CIM_CurveAuto:
case CIM_CurveAutoClamped:
case CIM_CurveBreak:
case CIM_CurveUser:
return ERichCurveInterpMode::RCIM_Cubic;
case CIM_Linear:
return ERichCurveInterpMode::RCIM_Linear;
default:
return ERichCurveInterpMode::RCIM_None;
}
}
ERichCurveTangentMode FMatineeImportTools::MatineeInterpolationToRichCurveTangent( EInterpCurveMode CurveMode )
{
switch ( CurveMode )
{
case CIM_CurveBreak:
return ERichCurveTangentMode::RCTM_Break;
case CIM_CurveUser:
// Import auto-clamped curves as user curves because rich curves don't have support for clamped tangents, and if the
// user moves the converted keys, the tangents will get mangled.
case CIM_CurveAutoClamped:
return ERichCurveTangentMode::RCTM_User;
default:
return ERichCurveTangentMode::RCTM_Auto;
}
}
void CleanupCurveKeys(FMovieSceneDoubleChannel* InChannel)
{
FKeyDataOptimizationParams Params;
Params.bAutoSetInterpolation = true;
UE::MovieScene::Optimize(InChannel, Params);
}
void CleanupCurveKeys(FMovieSceneFloatChannel* InChannel)
{
FKeyDataOptimizationParams Params;
Params.bAutoSetInterpolation = true;
UE::MovieScene::Optimize(InChannel, Params);
}
bool FMatineeImportTools::TryConvertMatineeToggleToOutParticleKey( ETrackToggleAction ToggleAction, EParticleKey& OutParticleKey )
{
switch ( ToggleAction )
{
case ETrackToggleAction::ETTA_On:
OutParticleKey = EParticleKey::Activate;
return true;
case ETrackToggleAction::ETTA_Off:
OutParticleKey = EParticleKey::Deactivate;
return true;
case ETrackToggleAction::ETTA_Trigger:
OutParticleKey = EParticleKey::Trigger;
return true;
}
return false;
}
void FMatineeImportTools::SetOrAddKey(TMovieSceneChannelData<FMovieSceneFloatValue>& ChannelData, FFrameNumber Time, float Value, float ArriveTangent, float LeaveTangent, EInterpCurveMode MatineeInterpMode, FFrameRate FrameRate
, ERichCurveTangentWeightMode WeightedMode, float ArriveTangentWeight, float LeaveTangentWeight)
{
if (ChannelData.FindKey(Time) == INDEX_NONE)
{
FMovieSceneFloatValue NewKey(Value);
NewKey.InterpMode = MatineeInterpolationToRichCurveInterpolation( MatineeInterpMode );
NewKey.TangentMode = MatineeInterpolationToRichCurveTangent( MatineeInterpMode );
NewKey.Tangent.ArriveTangent = ArriveTangent / FrameRate.AsDecimal();
NewKey.Tangent.LeaveTangent = LeaveTangent / FrameRate.AsDecimal();
NewKey.Tangent.TangentWeightMode = WeightedMode;
NewKey.Tangent.ArriveTangentWeight = ArriveTangentWeight;
NewKey.Tangent.LeaveTangentWeight = LeaveTangentWeight;
ChannelData.AddKey( Time, NewKey );
}
}
void FMatineeImportTools::SetOrAddKey(TMovieSceneChannelData<FMovieSceneDoubleValue>& ChannelData, FFrameNumber Time, double Value, float ArriveTangent, float LeaveTangent, EInterpCurveMode MatineeInterpMode, FFrameRate FrameRate
, ERichCurveTangentWeightMode WeightedMode, float ArriveTangentWeight, float LeaveTangentWeight)
{
if (ChannelData.FindKey(Time) == INDEX_NONE)
{
FMovieSceneDoubleValue NewKey(Value);
NewKey.InterpMode = MatineeInterpolationToRichCurveInterpolation( MatineeInterpMode );
NewKey.TangentMode = MatineeInterpolationToRichCurveTangent( MatineeInterpMode );
NewKey.Tangent.ArriveTangent = ArriveTangent / FrameRate.AsDecimal();
NewKey.Tangent.LeaveTangent = LeaveTangent / FrameRate.AsDecimal();
NewKey.Tangent.TangentWeightMode = WeightedMode;
NewKey.Tangent.ArriveTangentWeight = ArriveTangentWeight;
NewKey.Tangent.LeaveTangentWeight = LeaveTangentWeight;
ChannelData.AddKey( Time, NewKey );
}
}
bool FMatineeImportTools::CopyInterpBoolTrack( UInterpTrackBoolProp* MatineeBoolTrack, UMovieSceneBoolTrack* BoolTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeFBoolTrack", "Paste Matinee Bool Track" ) );
bool bSectionCreated = false;
BoolTrack->Modify();
FFrameRate FrameRate = BoolTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeBoolTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneBoolSection* Section = Cast<UMovieSceneBoolSection>( MovieSceneHelpers::FindSectionAtTime( BoolTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneBoolSection>( BoolTrack->CreateNewSection() );
BoolTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
if (MatineeBoolTrack->BoolTrack.Num() == 1)
{
Section->GetChannel().SetDefault(MatineeBoolTrack->BoolTrack[0].Value);
}
}
if (Section->TryModify())
{
if (MatineeBoolTrack->BoolTrack.Num() > 1)
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
TMovieSceneChannelData<bool> ChannelData = Section->GetChannelProxy().GetChannel<FMovieSceneBoolChannel>(0)->GetData();
for ( const auto& Point : MatineeBoolTrack->BoolTrack )
{
FFrameNumber KeyTime = (Point.Time * FrameRate).RoundToFrame();
ChannelData.UpdateOrAddKey(KeyTime, Point.Value);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !KeyRange.IsEmpty())
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpFloatTrack( UInterpTrackFloatBase* MatineeFloatTrack, UMovieSceneFloatTrack* FloatTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeFloatTrack", "Paste Matinee Float Track" ) );
bool bSectionCreated = false;
FloatTrack->Modify();
FFrameRate FrameRate = FloatTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeFloatTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();;
UMovieSceneFloatSection* Section = Cast<UMovieSceneFloatSection>( MovieSceneHelpers::FindSectionAtTime( FloatTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneFloatSection>( FloatTrack->CreateNewSection() );
FloatTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
if (MatineeFloatTrack->FloatTrack.Points.Num() == 1)
{
FMovieSceneFloatChannel* FloatChannel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(0);
FloatChannel->SetDefault(MatineeFloatTrack->FloatTrack.Points[0].OutVal);
}
}
if (Section->TryModify())
{
if (MatineeFloatTrack->FloatTrack.Points.Num() > 1)
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
FMovieSceneFloatChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(0);
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData = Channel->GetData();
for ( const auto& Point : MatineeFloatTrack->FloatTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData, KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
CleanupCurveKeys(Channel);
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !KeyRange.IsEmpty())
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpMaterialParamTrack(UInterpTrackFloatMaterialParam* MatineeMaterialParamTrack, UMovieSceneComponentMaterialTrack * MaterialTrack)
{
const FScopedTransaction Transaction(NSLOCTEXT("Sequencer", "PasteMatineeFloatMaterialParamTrack", "Paste Matinee Float Material Param Track"));
bool bSectionCreated = false;
MaterialTrack->Modify();
FFrameRate FrameRate = MaterialTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeMaterialParamTrack->GetKeyframeTime(0) * FrameRate).RoundToFrame();
UMovieSceneParameterSection* Section = Cast<UMovieSceneParameterSection>(MovieSceneHelpers::FindSectionAtTime(MaterialTrack->GetAllSections(), FirstKeyTime));
if (Section == nullptr)
{
Section = Cast<UMovieSceneParameterSection>(MaterialTrack->CreateNewSection());
MaterialTrack->AddSection(*Section);
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
auto FirstPoint = MatineeMaterialParamTrack->FloatTrack.Points[0];
FFrameNumber KeyTime = (FirstPoint.InVal * FrameRate).RoundToFrame();
// The section needs a key added to be initialized, so add the first key from the matinee track.
Section->AddScalarParameterKey(MatineeMaterialParamTrack->ParamName, KeyTime, FirstPoint.OutVal);
TArray<FScalarParameterNameAndCurve> ScalarParms = Section->GetScalarParameterNamesAndCurves();
FMovieSceneFloatChannel* Channel = nullptr;
int32 CurveIndex = 0;
for (FScalarParameterNameAndCurve NameAndCurve : ScalarParms)
{
if (NameAndCurve.ParameterName == MatineeMaterialParamTrack->ParamName)
{
Channel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(CurveIndex);
break;
}
++CurveIndex;
}
if (!Channel)
{
return false;
}
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData = Channel->GetData();
for (const auto& Point : MatineeMaterialParamTrack->FloatTrack.Points)
{
FFrameNumber CurrentKeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey(ChannelData, CurrentKeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
}
CleanupCurveKeys(Channel);
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpMaterialParamTrack(UInterpTrackVectorMaterialParam * MatineeMaterialParamTrack, UMovieSceneComponentMaterialTrack * MaterialTrack)
{
const FScopedTransaction Transaction(NSLOCTEXT("Sequencer", "PasteMatineeFloatMaterialParamTrack", "Paste Matinee Float Material Param Track"));
bool bSectionCreated = false;
MaterialTrack->Modify();
FFrameRate FrameRate = MaterialTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeMaterialParamTrack->GetKeyframeTime(0) * FrameRate).RoundToFrame();
UMovieSceneParameterSection* Section = Cast<UMovieSceneParameterSection>(MovieSceneHelpers::FindSectionAtTime(MaterialTrack->GetAllSections(), FirstKeyTime));
if (Section == nullptr)
{
Section = Cast<UMovieSceneParameterSection>(MaterialTrack->CreateNewSection());
MaterialTrack->AddSection(*Section);
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
FInterpCurvePointVector FirstPoint = MatineeMaterialParamTrack->VectorTrack.Points[0];
FFrameNumber KeyTime = (FirstPoint.InVal * FrameRate).RoundToFrame();
// The section needs a key added to be initialized, so add the first key from the matinee track.
Section->AddVectorParameterKey(MatineeMaterialParamTrack->ParamName, KeyTime, FirstPoint.OutVal);
TArray<FScalarParameterNameAndCurve> ScalarParms = Section->GetScalarParameterNamesAndCurves();
FMovieSceneFloatChannel* Channel = nullptr;
int32 CurveIndex = 0;
for (FScalarParameterNameAndCurve NameAndCurve : ScalarParms)
{
if (NameAndCurve.ParameterName == MatineeMaterialParamTrack->ParamName)
{
Channel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(CurveIndex);
break;
}
++CurveIndex;
}
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData[3] = {
Channels[CurveIndex]->GetData(), Channels[CurveIndex + 1]->GetData(), Channels[CurveIndex + 2]->GetData()
};
for (const auto& Point : MatineeMaterialParamTrack->VectorTrack.Points)
{
FFrameNumber CurrentKeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey(ChannelData[0], CurrentKeyTime, Point.OutVal.X, Point.ArriveTangent.X, Point.LeaveTangent.X, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey(ChannelData[1], CurrentKeyTime, Point.OutVal.Y, Point.ArriveTangent.Y, Point.LeaveTangent.Y, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey(ChannelData[2], CurrentKeyTime, Point.OutVal.Z, Point.ArriveTangent.Z, Point.LeaveTangent.Z, Point.InterpMode, FrameRate);
}
CleanupCurveKeys(Channels[0]);
CleanupCurveKeys(Channels[1]);
CleanupCurveKeys(Channels[2]);
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpVectorTrack( UInterpTrackVectorProp* MatineeVectorTrack, UMovieSceneFloatVectorTrack* VectorTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeVectorTrack", "Paste Matinee Vector Track" ) );
bool bSectionCreated = false;
VectorTrack->Modify();
FFrameRate FrameRate = VectorTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeVectorTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneFloatVectorSection* Section = Cast<UMovieSceneFloatVectorSection>( MovieSceneHelpers::FindSectionAtTime( VectorTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneFloatVectorSection>( VectorTrack->CreateNewSection() );
VectorTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
if (MatineeVectorTrack->VectorTrack.Points.Num() == 1)
{
if (Section->GetChannelsUsed() == 3)
{
const FInterpCurvePoint<FVector> FirstPoint = MatineeVectorTrack->VectorTrack.Points[0];
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
Channels[0]->SetDefault(FirstPoint.OutVal.X);
Channels[1]->SetDefault(FirstPoint.OutVal.Y);
Channels[2]->SetDefault(FirstPoint.OutVal.Z);
}
}
}
if (Section->TryModify())
{
if (MatineeVectorTrack->VectorTrack.Points.Num() > 1)
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
if (Section->GetChannelsUsed() == 3)
{
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData[3] = { Channels[0]->GetData(), Channels[1]->GetData(), Channels[2]->GetData() };
for ( const auto& Point : MatineeVectorTrack->VectorTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[0], KeyTime, Point.OutVal.X, Point.ArriveTangent.X, Point.LeaveTangent.X, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[1], KeyTime, Point.OutVal.Y, Point.ArriveTangent.Y, Point.LeaveTangent.Y, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[2], KeyTime, Point.OutVal.Z, Point.ArriveTangent.Z, Point.LeaveTangent.Z, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
CleanupCurveKeys(Channels[0]);
CleanupCurveKeys(Channels[1]);
CleanupCurveKeys(Channels[2]);
}
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !KeyRange.IsEmpty())
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpColorTrack( UInterpTrackColorProp* ColorPropTrack, UMovieSceneColorTrack* ColorTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeColorTrack", "Paste Matinee Color Track" ) );
bool bSectionCreated = false;
ColorTrack->Modify();
FFrameRate FrameRate = ColorTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (ColorPropTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneColorSection* Section = Cast<UMovieSceneColorSection>( MovieSceneHelpers::FindSectionAtTime( ColorTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneColorSection>( ColorTrack->CreateNewSection() );
ColorTrack->AddSection( *Section );
TArrayView<FMovieSceneFloatChannel*> FloatChannels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
FloatChannels[0]->SetDefault(0.f);
FloatChannels[1]->SetDefault(0.f);
FloatChannels[2]->SetDefault(0.f);
FloatChannels[3]->SetDefault(1.f);
if (ColorPropTrack->VectorTrack.Points.Num() == 1)
{
const FInterpCurvePoint<FVector> FirstPoint = ColorPropTrack->VectorTrack.Points[0];
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
Channels[0]->SetDefault(FirstPoint.OutVal.X);
Channels[1]->SetDefault(FirstPoint.OutVal.Y);
Channels[2]->SetDefault(FirstPoint.OutVal.Z);
}
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
if (ColorPropTrack->VectorTrack.Points.Num() > 1)
{
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData[3] = { Channels[0]->GetData(), Channels[1]->GetData(), Channels[2]->GetData() };
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
for ( const FInterpCurvePoint<FVector>& Point : ColorPropTrack->VectorTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[0], KeyTime, Point.OutVal.X, Point.ArriveTangent.X, Point.LeaveTangent.X, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[1], KeyTime, Point.OutVal.Y, Point.ArriveTangent.Y, Point.LeaveTangent.Y, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[2], KeyTime, Point.OutVal.Z, Point.ArriveTangent.Z, Point.LeaveTangent.Z, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
CleanupCurveKeys(Channels[0]);
CleanupCurveKeys(Channels[1]);
CleanupCurveKeys(Channels[2]);
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !KeyRange.IsEmpty())
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpLinearColorTrack( UInterpTrackLinearColorProp* LinearColorPropTrack, UMovieSceneColorTrack* ColorTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeLinearColorTrack", "Paste Matinee Linear Color Track" ) );
bool bSectionCreated = false;
ColorTrack->Modify();
FFrameRate FrameRate = ColorTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (LinearColorPropTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneColorSection* Section = Cast<UMovieSceneColorSection>( MovieSceneHelpers::FindSectionAtTime( ColorTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneColorSection>( ColorTrack->CreateNewSection() );
ColorTrack->AddSection( *Section );
TArrayView<FMovieSceneFloatChannel*> FloatChannels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
FloatChannels[0]->SetDefault(0.f);
FloatChannels[1]->SetDefault(0.f);
FloatChannels[2]->SetDefault(0.f);
FloatChannels[3]->SetDefault(1.f);
if (LinearColorPropTrack->LinearColorTrack.Points.Num() == 1)
{
const FInterpCurvePoint<FLinearColor> FirstPoint = LinearColorPropTrack->LinearColorTrack.Points[0];
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
Channels[0]->SetDefault(FirstPoint.OutVal.R);
Channels[1]->SetDefault(FirstPoint.OutVal.G);
Channels[2]->SetDefault(FirstPoint.OutVal.B);
Channels[3]->SetDefault(FirstPoint.OutVal.A);
}
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
if (LinearColorPropTrack->LinearColorTrack.Points.Num() > 1)
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
TArrayView<FMovieSceneFloatChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
TMovieSceneChannelData<FMovieSceneFloatValue> ChannelData[4] = { Channels[0]->GetData(), Channels[1]->GetData(), Channels[2]->GetData(), Channels[3]->GetData() };
for ( const auto& Point : LinearColorPropTrack->LinearColorTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[0], KeyTime, Point.OutVal.R, Point.ArriveTangent.R, Point.LeaveTangent.R, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[1], KeyTime, Point.OutVal.G, Point.ArriveTangent.G, Point.LeaveTangent.G, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[2], KeyTime, Point.OutVal.B, Point.ArriveTangent.B, Point.LeaveTangent.B, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[3], KeyTime, Point.OutVal.A, Point.ArriveTangent.A, Point.LeaveTangent.A, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
CleanupCurveKeys(Channels[0]);
CleanupCurveKeys(Channels[1]);
CleanupCurveKeys(Channels[2]);
CleanupCurveKeys(Channels[3]);
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !KeyRange.IsEmpty())
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpMoveTrack( UInterpTrackMove* MoveTrack, UMovieScene3DTransformTrack* TransformTrack, const FVector& DefaultScale )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeMoveTrack", "Paste Matinee Move Track" ) );
bool bSectionCreated = false;
TransformTrack->Modify();
FFrameRate FrameRate = TransformTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MoveTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieScene3DTransformSection* Section = Cast<UMovieScene3DTransformSection>( MovieSceneHelpers::FindSectionAtTime( TransformTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieScene3DTransformSection>( TransformTrack->CreateNewSection() );
TransformTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
TArrayView<FMovieSceneDoubleChannel*> DoubleChannels = Section->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
DoubleChannels[6]->SetDefault(DefaultScale.X);
DoubleChannels[7]->SetDefault(DefaultScale.Y);
DoubleChannels[8]->SetDefault(DefaultScale.Z);
}
if (Section->TryModify())
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
TArrayView<FMovieSceneDoubleChannel*> Channels = Section->GetChannelProxy().GetChannels<FMovieSceneDoubleChannel>();
TMovieSceneChannelData<FMovieSceneDoubleValue> ChannelData[6] = {
Channels[0]->GetData(), Channels[1]->GetData(), Channels[2]->GetData(),
Channels[3]->GetData(), Channels[4]->GetData(), Channels[5]->GetData()
};
for ( const auto& Point : MoveTrack->PosTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[0], KeyTime, Point.OutVal.X, Point.ArriveTangent.X, Point.LeaveTangent.X, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[1], KeyTime, Point.OutVal.Y, Point.ArriveTangent.Y, Point.LeaveTangent.Y, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[2], KeyTime, Point.OutVal.Z, Point.ArriveTangent.Z, Point.LeaveTangent.Z, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
for ( const auto& Point : MoveTrack->EulerTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[3], KeyTime, Point.OutVal.X, Point.ArriveTangent.X, Point.LeaveTangent.X, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[4], KeyTime, Point.OutVal.Y, Point.ArriveTangent.Y, Point.LeaveTangent.Y, Point.InterpMode, FrameRate);
FMatineeImportTools::SetOrAddKey( ChannelData[5], KeyTime, Point.OutVal.Z, Point.ArriveTangent.Z, Point.LeaveTangent.Z, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
for (auto SubTrack : MoveTrack->SubTracks)
{
if (SubTrack->IsA(UInterpTrackMoveAxis::StaticClass()))
{
UInterpTrackMoveAxis* MoveSubTrack = Cast<UInterpTrackMoveAxis>(SubTrack);
if (MoveSubTrack)
{
int32 ChannelIndex = INDEX_NONE;
if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_TranslationX)
{
ChannelIndex = 0;
}
else if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_TranslationY)
{
ChannelIndex = 1;
}
else if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_TranslationZ)
{
ChannelIndex = 2;
}
else if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_RotationX)
{
ChannelIndex = 3;
}
else if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_RotationY)
{
ChannelIndex = 4;
}
else if (MoveSubTrack->MoveAxis == EInterpMoveAxis::AXIS_RotationZ)
{
ChannelIndex = 5;
}
if (ChannelIndex != INDEX_NONE)
{
for (const auto& Point : MoveSubTrack->FloatTrack.Points)
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( ChannelData[ChannelIndex], KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
}
}
}
}
CleanupCurveKeys(Channels[0]);
CleanupCurveKeys(Channels[1]);
CleanupCurveKeys(Channels[2]);
CleanupCurveKeys(Channels[3]);
CleanupCurveKeys(Channels[4]);
CleanupCurveKeys(Channels[5]);
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !UE::MovieScene::IsEmptyOrZeroSize(KeyRange))
{
Section->SetRange( KeyRange );
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpParticleTrack( UInterpTrackToggle* MatineeToggleTrack, UMovieSceneParticleTrack* ParticleTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeParticleTrack", "Paste Matinee Particle Track" ) );
bool bSectionCreated = false;
ParticleTrack->Modify();
FFrameRate FrameRate = ParticleTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeToggleTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneParticleSection* Section = Cast<UMovieSceneParticleSection>( MovieSceneHelpers::FindSectionAtTime( ParticleTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneParticleSection>( ParticleTrack->CreateNewSection() );
ParticleTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
FMovieSceneParticleChannel* ParticleChannel = Section->GetChannelProxy().GetChannel<FMovieSceneParticleChannel>(0);
check(ParticleChannel);
TMovieSceneChannelData<uint8> ChannelData = ParticleChannel->GetData();
for ( const auto& Key : MatineeToggleTrack->ToggleTrack )
{
FFrameNumber KeyTime = (Key.Time * FrameRate).RoundToFrame();
EParticleKey ParticleKey;
if ( TryConvertMatineeToggleToOutParticleKey( Key.ToggleAction, ParticleKey ) )
{
ChannelData.AddKey( KeyTime, (uint8)ParticleKey );
}
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !UE::MovieScene::IsEmptyOrZeroSize(KeyRange))
{
Section->SetRange( KeyRange );
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpAnimControlTrack( UInterpTrackAnimControl* MatineeAnimControlTrack, UMovieSceneSkeletalAnimationTrack* SkeletalAnimationTrack, FFrameNumber EndPlaybackRange )
{
// @todo - Sequencer - Add support for slot names once they are implemented.
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeAnimTrack", "Paste Matinee Anim Track" ) );
bool bSectionCreated = false;
FFrameRate FrameRate = SkeletalAnimationTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
SkeletalAnimationTrack->Modify();
SkeletalAnimationTrack->RemoveAllAnimationData();
for (int32 i = 0; i < MatineeAnimControlTrack->AnimSeqs.Num(); i++)
{
const auto& AnimSeq = MatineeAnimControlTrack->AnimSeqs[i];
float EndTime;
if( AnimSeq.bLooping )
{
if( i < MatineeAnimControlTrack->AnimSeqs.Num() - 1 )
{
EndTime = MatineeAnimControlTrack->AnimSeqs[i + 1].StartTime;
}
else
{
EndTime = EndPlaybackRange / FrameRate;
}
}
else
{
EndTime = AnimSeq.StartTime + ( ( ( AnimSeq.AnimSeq->GetPlayLength() - AnimSeq.AnimEndOffset ) - AnimSeq.AnimStartOffset ) / AnimSeq.AnimPlayRate );
// Clamp to next clip's start time
if (i+1 < MatineeAnimControlTrack->AnimSeqs.Num())
{
float NextStartTime = MatineeAnimControlTrack->AnimSeqs[i+1].StartTime;
EndTime = FMath::Min(NextStartTime, EndTime);
}
}
UMovieSceneSkeletalAnimationSection* NewSection = Cast<UMovieSceneSkeletalAnimationSection>( SkeletalAnimationTrack->CreateNewSection() );
NewSection->SetRange( TRange<FFrameNumber>((AnimSeq.StartTime * FrameRate).RoundToFrame(), (EndTime * FrameRate).RoundToFrame() + 1) );
NewSection->Params.StartFrameOffset = FrameRate.AsFrameNumber(AnimSeq.AnimStartOffset);
NewSection->Params.EndFrameOffset = FrameRate.AsFrameNumber(AnimSeq.AnimEndOffset);
NewSection->Params.PlayRate = AnimSeq.AnimPlayRate;
NewSection->Params.Animation = AnimSeq.AnimSeq;
NewSection->Params.SlotName = MatineeAnimControlTrack->SlotName;
// Matinee behavior is that animation sections hold their value after they end but Sequencer properly handles save/load restore
// so we need to change the default behavior of the section to mimick Matinee more.
NewSection->SetCompletionMode(EMovieSceneCompletionMode::KeepState);
SkeletalAnimationTrack->AddSection( *NewSection );
bSectionCreated = true;
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpSoundTrack( UInterpTrackSound* MatineeSoundTrack, UMovieSceneAudioTrack* AudioTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeSoundTrack", "Paste Matinee Sound Track" ) );
bool bSectionCreated = false;
FFrameRate FrameRate = AudioTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
AudioTrack->Modify();
int MaxSectionRowIndex = -1;
for ( UMovieSceneSection* Section : AudioTrack->GetAllSections() )
{
MaxSectionRowIndex = FMath::Max( MaxSectionRowIndex, Section->GetRowIndex() );
}
for ( const FSoundTrackKey& SoundTrackKey : MatineeSoundTrack->Sounds )
{
// AddNewSound automatically adds the new section to the track list, so no need to do it later.
AudioTrack->AddNewSound( SoundTrackKey.Sound, (SoundTrackKey.Time * FrameRate).RoundToFrame() );
UMovieSceneAudioSection* NewAudioSection = Cast<UMovieSceneAudioSection>(AudioTrack->GetAllSections().Last());
NewAudioSection->SetRowIndex( MaxSectionRowIndex + 1 );
TArrayView<FMovieSceneFloatChannel*> FloatChannels = NewAudioSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();
FloatChannels[0]->SetDefault(SoundTrackKey.Volume);
FloatChannels[1]->SetDefault(SoundTrackKey.Pitch);
bSectionCreated = true;
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpFadeTrack( UInterpTrackFade* MatineeFadeTrack, UMovieSceneFadeTrack* FadeTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeFadeTrack", "Paste Matinee Fade Track" ) );
bool bSectionCreated = false;
FadeTrack->Modify();
FFrameRate FrameRate = FadeTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeFadeTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneFadeSection* Section = Cast<UMovieSceneFadeSection>( MovieSceneHelpers::FindSectionAtTime( FadeTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneFadeSection>( FadeTrack->CreateNewSection() );
FadeTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
FMovieSceneFloatChannel* FadeChannel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(0);
check(FadeChannel);
TMovieSceneChannelData<FMovieSceneFloatValue> FadeInterface = FadeChannel->GetData();
for ( const auto& Point : MatineeFadeTrack->FloatTrack.Points )
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey( FadeInterface, KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !UE::MovieScene::IsEmptyOrZeroSize(KeyRange))
{
Section->SetRange( KeyRange );
}
Section->FadeColor = MatineeFadeTrack->FadeColor;
Section->bFadeAudio = MatineeFadeTrack->bFadeAudio;
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpDirectorTrack( UInterpTrackDirector* DirectorTrack, UMovieSceneCameraCutTrack* CameraCutTrack, AMatineeActor* MatineeActor, IMovieScenePlayer& Player )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeDirectorTrack", "Paste Matinee Director Track" ) );
bool bCutsAdded = false;
FFrameRate FrameRate = CameraCutTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
CameraCutTrack->Modify();
for (FDirectorTrackCut TrackCut : DirectorTrack->CutTrack)
{
int32 GroupIndex = MatineeActor->MatineeData->FindGroupByName(TrackCut.TargetCamGroup);
UInterpGroupInst* ViewGroupInst = (GroupIndex != INDEX_NONE) ? MatineeActor->FindFirstGroupInstByName( TrackCut.TargetCamGroup.ToString() ) : NULL;
if ( GroupIndex != INDEX_NONE && ViewGroupInst )
{
// Find a valid move track for this cut.
UInterpGroup* Group = MatineeActor->MatineeData->InterpGroups[GroupIndex];
if (Group)
{
AActor* CameraActor = ViewGroupInst->GetGroupActor();
FGuid CameraHandle = Player.FindObjectId(*CameraActor, MovieSceneSequenceID::Root);
if (CameraHandle.IsValid())
{
CameraCutTrack->AddNewCameraCut(UE::MovieScene::FRelativeObjectBindingID(CameraHandle), (TrackCut.Time * FrameRate).RoundToFrame());
bCutsAdded = true;
}
}
}
}
return bCutsAdded;
}
bool FMatineeImportTools::CopyInterpEventTrack( UInterpTrackEvent* MatineeEventTrack, UMovieSceneEventTrack* EventTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeEventTrack", "Paste Matinee Event Track" ) );
bool bSectionCreated = false;
EventTrack->Modify();
if (MatineeEventTrack->EventTrack.Num())
{
FFrameRate FrameRate = EventTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeEventTrack->EventTrack[0].Time * FrameRate).RoundToFrame();
UMovieSceneEventTriggerSection* Section = Cast<UMovieSceneEventTriggerSection>( MovieSceneHelpers::FindSectionAtTime( EventTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneEventTriggerSection>( EventTrack->CreateNewSection() );
Section->SetRange(TRange<FFrameNumber>::All());
EventTrack->AddSection(*Section);
bSectionCreated = true;
}
UMovieSceneSequence* Sequence = Section->GetTypedOuter<UMovieSceneSequence>();
if (Section->TryModify())
{
FMovieSceneSequenceEditor* SequenceEditor = FMovieSceneSequenceEditor::Find(Sequence);
UBlueprint* SequenceDirectorBP = SequenceEditor ? SequenceEditor->GetOrCreateDirectorBlueprint(Sequence) : nullptr;
if (SequenceDirectorBP)
{
SequenceDirectorBP->Modify();
FMovieSceneEventUtils::BindEventSectionToBlueprint(Section, SequenceDirectorBP);
}
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
FMovieSceneEventChannel* EventChannel = Section->GetChannelProxy().GetChannel<FMovieSceneEventChannel>(0);
check(EventChannel);
TMovieSceneChannelData<FMovieSceneEvent> ChannelData = EventChannel->GetData();
TMap<FName, UK2Node_CustomEvent*> EventMap;
for (const FEventTrackKey& EventTrackKey : MatineeEventTrack->EventTrack)
{
FFrameNumber KeyTime = (EventTrackKey.Time * FrameRate).RoundToFrame();
FMovieSceneEvent Event;
UK2Node_CustomEvent* ExistingEndpoint = EventMap.FindRef(EventTrackKey.EventName);
if (ExistingEndpoint)
{
FMovieSceneEventUtils::SetEndpoint(&Event, Section, ExistingEndpoint, nullptr);
}
else if (SequenceDirectorBP)
{
FMovieSceneEventEndpointParameters Params;
Params.SanitizedEventName = TEXT("MatineeEvent");
UK2Node_CustomEvent* NewEndpoint = FMovieSceneEventUtils::CreateUserFacingEvent(SequenceDirectorBP, Params);
EventMap.Add(EventTrackKey.EventName, NewEndpoint);
FMovieSceneEventUtils::SetEndpoint(&Event, Section, NewEndpoint, nullptr);
}
ChannelData.AddKey(KeyTime, Event);
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpVisibilityTrack( UInterpTrackVisibility* MatineeVisibilityTrack, UMovieSceneVisibilityTrack* VisibilityTrack )
{
const FScopedTransaction Transaction( NSLOCTEXT( "Sequencer", "PasteMatineeVisibilityTrack", "Paste Matinee Visibility track" ) );
bool bSectionCreated = false;
VisibilityTrack->Modify();
if (MatineeVisibilityTrack->VisibilityTrack.Num())
{
FFrameRate FrameRate = VisibilityTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeVisibilityTrack->GetKeyframeTime( 0 ) * FrameRate).RoundToFrame();
UMovieSceneBoolSection* Section = Cast<UMovieSceneBoolSection>( MovieSceneHelpers::FindSectionAtTime( VisibilityTrack->GetAllSections(), FirstKeyTime ) );
if ( Section == nullptr )
{
Section = Cast<UMovieSceneBoolSection>( VisibilityTrack->CreateNewSection() );
VisibilityTrack->AddSection( *Section );
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
bool bVisible = true;
FMovieSceneBoolChannel* VisibilityChannel = Section->GetChannelProxy().GetChannel<FMovieSceneBoolChannel>(0);
check(VisibilityChannel);
TMovieSceneChannelData<bool> ChannelData = VisibilityChannel->GetData();
for (FVisibilityTrackKey VisibilityTrackKey : MatineeVisibilityTrack->VisibilityTrack)
{
if (VisibilityTrackKey.Action == EVisibilityTrackAction::EVTA_Hide)
{
bVisible = false;
}
else if (VisibilityTrackKey.Action == EVisibilityTrackAction::EVTA_Show)
{
bVisible = true;
}
else if (VisibilityTrackKey.Action == EVisibilityTrackAction::EVTA_Toggle)
{
bVisible = !bVisible;
}
FFrameNumber KeyTime = (VisibilityTrackKey.Time * FrameRate).RoundToFrame();
ChannelData.UpdateOrAddKey(KeyTime, bVisible);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !UE::MovieScene::IsEmptyOrZeroSize(KeyRange))
{
Section->SetRange( KeyRange );
}
}
}
return bSectionCreated;
}
bool FMatineeImportTools::CopyInterpSlomoTrack(UInterpTrackSlomo* MatineeSlomoTrack, UMovieSceneSlomoTrack* SlomoTrack)
{
const FScopedTransaction Transaction(NSLOCTEXT("Sequencer", "PasteMatineeSlomoTrack", "Paste Matinee Slomo Track"));
bool bSectionCreated = false;
SlomoTrack->Modify();
FFrameRate FrameRate = SlomoTrack->GetTypedOuter<UMovieScene>()->GetTickResolution();
FFrameNumber FirstKeyTime = (MatineeSlomoTrack->GetKeyframeTime(0) * FrameRate).RoundToFrame();
UMovieSceneSlomoSection* Section = Cast<UMovieSceneSlomoSection>(MovieSceneHelpers::FindSectionAtTime(SlomoTrack->GetAllSections(), FirstKeyTime));
if (Section == nullptr)
{
Section = Cast<UMovieSceneSlomoSection>(SlomoTrack->CreateNewSection());
SlomoTrack->AddSection(*Section);
Section->SetRange(TRange<FFrameNumber>::All());
bSectionCreated = true;
}
if (Section->TryModify())
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>::Empty();
FMovieSceneFloatChannel* SlomoChannel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(0);
check(SlomoChannel);
TMovieSceneChannelData<FMovieSceneFloatValue> SlomoInterface = SlomoChannel->GetData();
for (const auto& Point : MatineeSlomoTrack->FloatTrack.Points)
{
FFrameNumber KeyTime = (Point.InVal * FrameRate).RoundToFrame();
FMatineeImportTools::SetOrAddKey(SlomoInterface, KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
KeyRange = TRange<FFrameNumber>::Hull(KeyRange, TRange<FFrameNumber>(KeyTime));
}
CleanupCurveKeys(SlomoChannel);
if (SectionRangeMode == EMatineeImportSectionRangeMode::KeysHull && !UE::MovieScene::IsEmptyOrZeroSize(KeyRange))
{
Section->SetRange(KeyRange);
}
}
return bSectionCreated;
}