FGuid FSequencer::GetHandleToObject( UObject* Object ) { TSharedRef<FMovieSceneInstance> FocusedMovieSceneInstance = GetFocusedMovieSceneInstance(); UMovieScene* FocusedMovieScene = FocusedMovieSceneInstance->GetMovieScene(); FGuid ObjectGuid = ObjectBindingManager->FindGuidForObject( *FocusedMovieScene, *Object ); if (ObjectGuid.IsValid()) { // Make sure that the possessable is still valid, if it's not remove the binding so new one // can be created. This can happen due to undo. FMovieScenePossessable* Possessable = FocusedMovieScene->FindPossessable(ObjectGuid); if (Possessable == nullptr ) { ObjectBindingManager->UnbindPossessableObjects(ObjectGuid); ObjectGuid.Invalidate(); } } bool bPossessableAdded = false; // If the object guid was not found attempt to add it // Note: Only possessed actors can be added like this if( !ObjectGuid.IsValid() && ObjectBindingManager->CanPossessObject( *Object ) ) { // @todo sequencer: Undo doesn't seem to be working at all const FScopedTransaction Transaction( LOCTEXT("UndoPossessingObject", "Possess Object with MovieScene") ); // Possess the object! { // Create a new possessable FocusedMovieScene->Modify(); ObjectGuid = FocusedMovieScene->AddPossessable( Object->GetName(), Object->GetClass() ); if ( IsShotFilteringOn() ) { AddUnfilterableObject(ObjectGuid); } ObjectBindingManager->BindPossessableObject( ObjectGuid, *Object ); bPossessableAdded = true; } } if( bPossessableAdded ) { SpawnOrDestroyPuppetObjects( GetFocusedMovieSceneInstance() ); NotifyMovieSceneDataChanged(); } return ObjectGuid; }
void FSequencer::OnActorsDropped( const TArray<TWeakObjectPtr<AActor> >& Actors ) { bool bPossessableAdded = false; for( TWeakObjectPtr<AActor> WeakActor : Actors ) { AActor* Actor = WeakActor.Get(); if( Actor != NULL ) { // Grab the MovieScene that is currently focused. We'll add our Blueprint as an inner of the // MovieScene asset. UMovieScene* OwnerMovieScene = GetFocusedMovieScene(); // @todo sequencer: Undo doesn't seem to be working at all const FScopedTransaction Transaction( LOCTEXT("UndoPossessingObject", "Possess Object with MovieScene") ); // Possess the object! { // Create a new possessable OwnerMovieScene->Modify(); const FGuid PossessableGuid = OwnerMovieScene->AddPossessable( Actor->GetActorLabel(), Actor->GetClass() ); if ( IsShotFilteringOn() ) { AddUnfilterableObject(PossessableGuid); } ObjectBindingManager->BindPossessableObject( PossessableGuid, *Actor ); bPossessableAdded = true; } } } if( bPossessableAdded ) { SpawnOrDestroyPuppetObjects( GetFocusedMovieSceneInstance() ); NotifyMovieSceneDataChanged(); } }
TSharedPtr<FMovieSceneAnimationSectionRecorder> UActorRecording::StartRecordingComponentProperties(const FName& BindingName, USceneComponent* SceneComponent, UObject* BindingContext, ULevelSequence* CurrentSequence, float CurrentSequenceTime, const FAnimationRecordingSettings& InAnimationSettings) { // first create a possessable for this component to be controlled by UMovieScene* OwnerMovieScene = CurrentSequence->GetMovieScene(); const FGuid PossessableGuid = OwnerMovieScene->AddPossessable(BindingName.ToString(), SceneComponent->GetClass()); // Set up parent/child guids for possessables within spawnables FMovieScenePossessable* ChildPossessable = OwnerMovieScene->FindPossessable(PossessableGuid); if (ensure(ChildPossessable)) { ChildPossessable->SetParent(Guid); } FMovieSceneSpawnable* ParentSpawnable = OwnerMovieScene->FindSpawnable(Guid); if (ParentSpawnable) { ParentSpawnable->AddChildPossessable(PossessableGuid); } // BindingName must be the component's path relative to its owner Actor FLevelSequenceObjectReference ObjectReference(FUniqueObjectGuid(), BindingName.ToString()); CurrentSequence->BindPossessableObject(PossessableGuid, ObjectReference); // First try built-in animation recorder... TSharedPtr<FMovieSceneAnimationSectionRecorder> AnimationRecorder = nullptr; if (FSequenceRecorder::Get().GetAnimationRecorderFactory().CanRecordObject(SceneComponent)) { AnimationRecorder = FSequenceRecorder::Get().GetAnimationRecorderFactory().CreateSectionRecorder(this, InAnimationSettings); AnimationRecorder->CreateSection(SceneComponent, OwnerMovieScene, PossessableGuid, CurrentSequenceTime); AnimationRecorder->Record(CurrentSequenceTime); SectionRecorders.Add(AnimationRecorder); } // ...and transform... if (FSequenceRecorder::Get().GetTransformRecorderFactory().CanRecordObject(SceneComponent)) { TSharedPtr<IMovieSceneSectionRecorder> Recorder = FSequenceRecorder::Get().GetTransformRecorderFactory().CreateSectionRecorder(true, nullptr); if (Recorder.IsValid()) { Recorder->CreateSection(SceneComponent, OwnerMovieScene, PossessableGuid, CurrentSequenceTime); Recorder->Record(CurrentSequenceTime); SectionRecorders.Add(Recorder); } } // ...now any external recorders TArray<IMovieSceneSectionRecorderFactory*> ModularFeatures = IModularFeatures::Get().GetModularFeatureImplementations<IMovieSceneSectionRecorderFactory>(MovieSceneSectionRecorderFactoryName); for (IMovieSceneSectionRecorderFactory* Factory : ModularFeatures) { if (Factory->CanRecordObject(SceneComponent)) { TSharedPtr<IMovieSceneSectionRecorder> Recorder = Factory->CreateSectionRecorder(ActorSettings); if (Recorder.IsValid()) { Recorder->CreateSection(SceneComponent, OwnerMovieScene, PossessableGuid, CurrentSequenceTime); Recorder->Record(CurrentSequenceTime); SectionRecorders.Add(Recorder); } } } return AnimationRecorder; }
void UActorRecording::StartRecordingActorProperties(ULevelSequence* CurrentSequence, float CurrentSequenceTime) { if(CurrentSequence != nullptr) { // set up our spawnable or possessable for this actor UMovieScene* MovieScene = CurrentSequence->GetMovieScene(); AActor* Actor = GetActorToRecord(); if (bRecordToPossessable) { Guid = MovieScene->AddPossessable(Actor->GetActorLabel(), Actor->GetClass()); CurrentSequence->BindPossessableObject(Guid, *Actor, Actor->GetWorld()); } else { FString TemplateName = GetUniqueSpawnableName(MovieScene, Actor->GetName()); AActor* ObjectTemplate = CastChecked<AActor>(CurrentSequence->MakeSpawnableTemplateFromInstance(*Actor, *TemplateName)); if (ObjectTemplate) { TInlineComponentArray<USkeletalMeshComponent*> SkeletalMeshComponents; ObjectTemplate->GetComponents(SkeletalMeshComponents); for (USkeletalMeshComponent* SkeletalMeshComponent : SkeletalMeshComponents) { SkeletalMeshComponent->SetAnimationMode(EAnimationMode::AnimationSingleNode); SkeletalMeshComponent->bEnableUpdateRateOptimizations = false; SkeletalMeshComponent->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPoseAndRefreshBones; SkeletalMeshComponent->ForcedLodModel = 1; } Guid = MovieScene->AddSpawnable(TemplateName, *ObjectTemplate); } } // now add tracks to record if(Guid.IsValid()) { // add our folder FindOrAddFolder(MovieScene); // force set recording to record translations as we need this with no animation UMovieScene3DTransformSectionRecorderSettings* TransformSettings = ActorSettings.GetSettingsObject<UMovieScene3DTransformSectionRecorderSettings>(); check(TransformSettings); TransformSettings->bRecordTransforms = true; // grab components so we can track attachments // don't include non-CDO here as they wont be part of our initial BP (duplicated above) // we will catch these 'extra' components on the first tick const bool bIncludeNonCDO = false; SyncTrackedComponents(bIncludeNonCDO); TInlineComponentArray<USceneComponent*> SceneComponents(GetActorToRecord()); // check if components need recording TInlineComponentArray<USceneComponent*> ValidSceneComponents; for(TWeakObjectPtr<USceneComponent>& SceneComponent : TrackedComponents) { if(ValidComponent(SceneComponent.Get())) { ValidSceneComponents.Add(SceneComponent.Get()); // add all parent components too TArray<USceneComponent*> ParentComponents; SceneComponent->GetParentComponents(ParentComponents); for(USceneComponent* ParentComponent : ParentComponents) { ValidSceneComponents.AddUnique(ParentComponent); } } } ProcessNewComponentArray(ValidSceneComponents); TSharedPtr<FMovieSceneAnimationSectionRecorder> FirstAnimRecorder = nullptr; for(USceneComponent* SceneComponent : ValidSceneComponents) { TSharedPtr<FMovieSceneAnimationSectionRecorder> AnimRecorder = StartRecordingComponentProperties(SceneComponent->GetFName(), SceneComponent, GetActorToRecord(), CurrentSequence, CurrentSequenceTime, AnimationSettings); if(!FirstAnimRecorder.IsValid() && AnimRecorder.IsValid() && GetActorToRecord()->IsA<ACharacter>()) { FirstAnimRecorder = AnimRecorder; } } // we need to create a transform track even if we arent recording transforms if (FSequenceRecorder::Get().GetTransformRecorderFactory().CanRecordObject(GetActorToRecord())) { TSharedPtr<IMovieSceneSectionRecorder> Recorder = FSequenceRecorder::Get().GetTransformRecorderFactory().CreateSectionRecorder(TransformSettings->bRecordTransforms, FirstAnimRecorder); if(Recorder.IsValid()) { Recorder->CreateSection(GetActorToRecord(), MovieScene, Guid, CurrentSequenceTime); Recorder->Record(CurrentSequenceTime); SectionRecorders.Add(Recorder); } } TArray<IMovieSceneSectionRecorderFactory*> ModularFeatures = IModularFeatures::Get().GetModularFeatureImplementations<IMovieSceneSectionRecorderFactory>(MovieSceneSectionRecorderFactoryName); for (IMovieSceneSectionRecorderFactory* Factory : ModularFeatures) { if (Factory->CanRecordObject(GetActorToRecord())) { TSharedPtr<IMovieSceneSectionRecorder> Recorder = Factory->CreateSectionRecorder(ActorSettings); if (Recorder.IsValid()) { Recorder->CreateSection(GetActorToRecord(), MovieScene, Guid, CurrentSequenceTime); Recorder->Record(CurrentSequenceTime); SectionRecorders.Add(Recorder); } } } } } }