void FSequencerActorBindingManager::SpawnOrDestroyObjectsForInstance( TSharedRef<FMovieSceneInstance> MovieSceneInstance, const bool bDestroyAll )
{
	bool bAnyLevelActorsChanged = false;

	// Get the list of puppet objects for the movie scene
	TArray< TSharedRef<FPuppetActorInfo> >& PuppetObjects = InstanceToPuppetObjectsMap.FindOrAdd( MovieSceneInstance );

	UMovieScene* MovieScene = MovieSceneInstance->GetMovieScene();

	// Remove any puppet objects that we no longer need
	{
		for( auto PuppetObjectIndex = 0; PuppetObjectIndex < PuppetObjects.Num(); ++PuppetObjectIndex )
		{
			if( PuppetObjects[ PuppetObjectIndex ]->GetType() == EPuppetObjectType::Actor )
			{
				TSharedRef< FPuppetActorInfo > PuppetActorInfo = StaticCastSharedRef< FPuppetActorInfo >( PuppetObjects[ PuppetObjectIndex ] );

				// Figure out if we still need this puppet actor
				bool bShouldDestroyActor = true;
				if( !bDestroyAll )
				{
					for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex )
					{
						auto& Spawnable = MovieScene->GetSpawnable( SpawnableIndex );
						if( Spawnable.GetGuid() == PuppetActorInfo->SpawnableGuid )
						{
							bShouldDestroyActor = false;
							break;
						}
					}
				}

				if( bShouldDestroyActor )
				{
					AActor* PuppetActor = PuppetActorInfo->PuppetActor.Get();
					if( PuppetActor != NULL )
					{
						UWorld* PuppetWorld = PuppetActor->GetWorld();
						if( ensure( PuppetWorld != NULL ) )
						{
							// Destroy this actor
							{
								// Ignored unless called while game is running
								const bool bNetForce = false;

								// We don't want to dirty the level for puppet actor changes
								const bool bShouldModifyLevel = false;

								if( !bAnyLevelActorsChanged )
								{
									DeselectAllPuppetObjects();
								}

								// Actor should never be selected in the editor at this point.  We took care of that up above.
								ensure( !PuppetActor->IsSelected() );

								const bool bWasDestroyed = PuppetWorld->DestroyActor( PuppetActor, bNetForce, bShouldModifyLevel );

								if( bWasDestroyed )
								{
									bAnyLevelActorsChanged = true;
									PuppetObjects.RemoveAt( PuppetObjectIndex-- );
								}
								else
								{
									// @todo sequencer: At least one puppet couldn't be cleaned up!
								}
							}
						}
					}
					else
					{
						// Actor is no longer valid (probably the world was destroyed)
					}
				}
			}
			else
			{
				check(0);	// Unhandled type
			}
		}
	}

	if( !bDestroyAll )
	{
		for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex )
		{
			FMovieSceneSpawnable& Spawnable = MovieScene->GetSpawnable( SpawnableIndex );

			// Must have a valid world for us to be able to do this
			if( ActorWorld != NULL )
			{
				// Do we already have a puppet for this spawnable?
				bool bIsAlreadySpawned = false;
				for( auto PuppetIndex = 0; PuppetIndex < PuppetObjects.Num(); ++PuppetIndex )
				{
					auto& PuppetObject = PuppetObjects[ PuppetIndex ];
					if( PuppetObject->SpawnableGuid == Spawnable.GetGuid() )
					{
						bIsAlreadySpawned = true;
						break;
					}
				}

				if( !bIsAlreadySpawned )
				{
					UClass* GeneratedClass = Spawnable.GetClass();
					if ( GeneratedClass != NULL && GeneratedClass->IsChildOf(AActor::StaticClass()))
					{
						AActor* ActorCDO = CastChecked< AActor >( GeneratedClass->ClassDefaultObject );

						const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation;
						const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation;

						// @todo sequencer: We should probably spawn these in a specific sub-level!
						// World->CurrentLevel = ???;

						const FName PuppetActorName = NAME_None;

						// Override the object flags so that RF_Transactional is not set.  Puppet actors are never transactional
						// @todo sequencer: These actors need to avoid any transaction history.  However, RF_Transactional can currently be set on objects on the fly!
						const EObjectFlags ObjectFlags = RF_Transient;		// NOTE: We are omitting RF_Transactional intentionally

						// @todo sequencer livecapture: Consider using SetPlayInEditorWorld() and RestoreEditorWorld() here instead
						
						// @todo sequencer actors: We need to make sure puppet objects aren't copied into PIE/SIE sessions!  They should be omitted from that duplication!

						// Spawn the puppet actor
						FActorSpawnParameters SpawnInfo;
						SpawnInfo.Name = PuppetActorName;
						SpawnInfo.ObjectFlags = ObjectFlags;
						AActor* NewActor = ActorWorld->SpawnActor( GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo );
				
						if( NewActor )
						{
							// @todo sequencer: We're naming the actor based off of the spawnable's name.  Is that really what we want?
							FActorLabelUtilities::SetActorLabelUnique(NewActor, Spawnable.GetName());

							// Actor was spawned OK!

							// Keep track of this actor
							TSharedRef< FPuppetActorInfo > NewPuppetInfo( new FPuppetActorInfo() );
							NewPuppetInfo->SpawnableGuid = Spawnable.GetGuid();
							NewPuppetInfo->PuppetActor = NewActor;
							PuppetObjects.Add( NewPuppetInfo );
						}
						else
						{
							// Actor failed to spawn
							// @todo sequencer: What should we do when this happens to one or more actors?
						}
					}
				}
			}
		}
	}
}
예제 #2
-1
void UActorAnimationPlayer::SpawnActorsForMovie(TSharedRef<FMovieSceneSequenceInstance> MovieSceneInstance)
{
	UWorld* WorldPtr = World.Get();

	if (WorldPtr == nullptr)
	{
		return;
	}

	UMovieScene* MovieScene = MovieSceneInstance->GetSequence()->GetMovieScene();

	if (MovieScene == nullptr)
	{
		return;
	}

	TArray<FSpawnedActorInfo>* FoundSpawnedActors = InstanceToSpawnedActorMap.Find(MovieSceneInstance);

	if (FoundSpawnedActors != nullptr)
	{
		// Remove existing spawned actors for this movie
		DestroyActorsForMovie( MovieSceneInstance );
	}

	TArray<FSpawnedActorInfo>& SpawnedActorList = InstanceToSpawnedActorMap.Add(MovieSceneInstance, TArray<FSpawnedActorInfo>());

	for (auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex)
	{
		auto& Spawnable = MovieScene->GetSpawnable(SpawnableIndex);
		UClass* GeneratedClass = Spawnable.GetClass();
		
		if ((GeneratedClass == nullptr) || !GeneratedClass->IsChildOf(AActor::StaticClass()))
		{
			continue;
		}

		AActor* ActorCDO = CastChecked<AActor>(GeneratedClass->ClassDefaultObject);
		const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation;
		const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation;

		FActorSpawnParameters SpawnInfo;
		{
			SpawnInfo.ObjectFlags = RF_NoFlags;
		}

		AActor* NewActor = WorldPtr->SpawnActor(GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo);

		if (NewActor)
		{	
			// Actor was spawned OK!
			FSpawnedActorInfo NewInfo;
			{
				NewInfo.RuntimeGuid = Spawnable.GetGuid();
				NewInfo.SpawnedActor = NewActor;
			}
						
			SpawnedActorList.Add(NewInfo);
		}
	}
}
void URuntimeMovieScenePlayer::SpawnActorsForMovie( TSharedRef<FMovieSceneInstance> MovieSceneInstance  )
{
	UWorld* WorldPtr = World.Get();
	if( WorldPtr != NULL && MovieSceneBindings != NULL )
	{
		UMovieScene* MovieScene = MovieSceneInstance->GetMovieScene();
		if( MovieScene != NULL )
		{
			TArray<FSpawnedActorInfo>* FoundSpawnedActors = InstanceToSpawnedActorMap.Find( MovieSceneInstance );
			if( FoundSpawnedActors )
			{
				// Remove existing spawned actors for this movie
				DestroyActorsForMovie( MovieSceneInstance );
			}

			TArray<FSpawnedActorInfo>& SpawnedActorList = InstanceToSpawnedActorMap.Add( MovieSceneInstance, TArray<FSpawnedActorInfo>() );

			for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex )
			{
				auto& Spawnable = MovieScene->GetSpawnable( SpawnableIndex );

				UClass* GeneratedClass = Spawnable.GetClass();
				if ( GeneratedClass != NULL )
				{
					const bool bIsActorBlueprint = GeneratedClass->IsChildOf( AActor::StaticClass() );
					if ( bIsActorBlueprint )
					{
						AActor* ActorCDO = CastChecked< AActor >( GeneratedClass->ClassDefaultObject );

						const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation;
						const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation;

						FActorSpawnParameters SpawnInfo;
						SpawnInfo.ObjectFlags = RF_NoFlags;
						AActor* NewActor = WorldPtr->SpawnActor( GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo );
						if( NewActor )
						{	
							// Actor was spawned OK!
							FSpawnedActorInfo NewInfo;
							NewInfo.RuntimeGuid = Spawnable.GetGuid();
							NewInfo.SpawnedActor = NewActor;
						
							SpawnedActorList.Add( NewInfo );
						}
					}
				}
			}
		}
	}
}