void UMovieScene3DAttachTrack::AddConstraint(float KeyTime, float ConstraintEndTime, const FGuid& ConstraintId)
{
	// add the section
	UMovieScene3DAttachSection* NewSection = NewObject<UMovieScene3DAttachSection>(this);
	NewSection->AddAttach(KeyTime, ConstraintEndTime, ConstraintId);
	NewSection->InitialPlacement( ConstraintSections, KeyTime, ConstraintEndTime, SupportsMultipleRows() );

	ConstraintSections.Add(NewSection);
}
UMovieSceneSection* UMovieScene3DAttachTrack::CreateNewSection()
{
	UMovieScene3DAttachSection* NewSection = NewObject<UMovieScene3DAttachSection>(this);
	NewSection->SetFlags(RF_Transactional);

	ConstraintSections.Add(NewSection);

	return NewSection;
}
void UMovieScene3DAttachTrack::AddConstraint(float KeyTime, float ConstraintEndTime, const FName SocketName, const FName ComponentName, const FGuid& ConstraintId)
{
	// add the section
	UMovieScene3DAttachSection* NewSection = NewObject<UMovieScene3DAttachSection>(this);
	NewSection->SetFlags(RF_Transactional);
	NewSection->AddAttach(KeyTime, ConstraintEndTime, ConstraintId);
	NewSection->InitialPlacement( ConstraintSections, KeyTime, ConstraintEndTime, SupportsMultipleRows() );
	NewSection->AttachSocketName = SocketName;
	NewSection->AttachComponentName = ComponentName;

	ConstraintSections.Add(NewSection);
}
void FMovieScene3DAttachTrackInstance::UpdateConstraint( float Position, const TArray<TWeakObjectPtr<UObject>>& RuntimeObjects, AActor* Actor, UMovieScene3DConstraintSection* ConstraintSection ) 
{
	FVector Translation;
	FRotator Rotation;

	UMovieScene3DAttachSection* AttachSection = CastChecked<UMovieScene3DAttachSection>(ConstraintSection);

	for( int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex )
	{
		USceneComponent* SceneComponent = MovieSceneHelpers::SceneComponentFromRuntimeObject(RuntimeObjects[ObjIndex].Get());

		if (SceneComponent != nullptr)
		{
			AttachSection->Eval(SceneComponent, Position, Actor, Translation, Rotation);

			// Set the relative translation and rotation.  Note they are set once instead of individually to avoid a redundant component transform update.
			SceneComponent->SetRelativeLocationAndRotation(Translation, Rotation);
		}
	}
}
void F3DAttachTrackEditor::ActorSocketPicked(const FName SocketName, AActor* ParentActor, FGuid ObjectGuid, UMovieSceneSection* Section)
{
	if (ObjectGuid.IsValid())
	{
		TArray<UObject*> OutObjects;
		GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneSequenceInstance(), ObjectGuid, OutObjects);

		AnimatablePropertyChanged( FOnKeyProperty::CreateRaw( this, &F3DAttachTrackEditor::AddKeyInternal, OutObjects, SocketName, ParentActor) );
	}
	else if (Section != nullptr)
	{
		const FScopedTransaction Transaction(LOCTEXT("UndoSetAttach", "Set Attach"));

		UMovieScene3DAttachSection* AttachSection = (UMovieScene3DAttachSection*)(Section);
		FGuid ActorId = FindOrCreateHandleToObject(ParentActor).Handle;

		if (ActorId.IsValid())
		{
			AttachSection->SetConstraintId(ActorId);
			AttachSection->AttachSocketName = SocketName;
		}
	}
}